0

I have a Web API and a very quick page I threw together to test it (the actual page that will call the API is/will be written by an outside vendor).

My Search action takes several parameters, all of which are optional and should default to empty strings.

[ActionName("Search")]
public IEnumerable<Foo> Get(string param1 = "", string param2 = "", string param3 = "")

And the View that calls the API:

@using (Ajax.BeginForm(new AjaxOptions { 
                       Url = ViewBag.APIUrl + "api/controller/Search",
                       HttpMethod = "GET",
                       OnSuccess = "successful" }))
{
    @Html.TextBox("param1")
    @Html.TextBox("param2")
    @Html.TextBox("param3")
}

The GET request looks like this

[...]/Search?param1=&param2=&param3=

Every value that is empty on the form is being passed to the API Controller as null, and thus the default values of empty strings are not being used. (It does pass actual values as expected.) As it is I'm null-coalescing these into empty strings after the fact, but the old version of this API did not have to do that.

When I add

int skip = 0, int take = 0

as parameters, I get the

The parameters dictionary contains a null entry

exception. I know this can be fixed by making those params nullable, then null-coalescing them like the strings. But purpose-wise, they should not be nullable, they should be optional with a default value.

How do I make it use the default values of the parameters in the action? Am I doing something wrong in the form, or in the API Controller?

CarenRose
  • 1,266
  • 1
  • 12
  • 24

1 Answers1

0

It is possible to use optional parameters if you change your API controller. Please refer to the following code snippet for an example (assuming Attribute Routing is used):

    [RoutePrefix("api/TestWebApi")]
    public class TestWebApiController : ApiController
    {
        [HttpGet]
        [Route("GetFoo")]
        public IQueryable<Foo> GetFoo(string param1 = "", string param2 = "", string param3 = "")
        {
             // your implementation
        }
    }

With the above controller, the following four test cases can be achieved :

Test case 1: Pass all three parameters

api/TestWebApi/GetFoo?param1=a&param2=b&param3=c

Test Case 2: pass param2 and param3

/api/TestWebApi/GetFoo?param2=b&param3=c

Test Case 3: pass param3

/api/TestWebApi/GetFoo?param3=c

Test case 4: use default values:

/api/TestWebApi/GetFoo

Hope this helps.

Ping
  • 124
  • 3
  • To clarify: What you're suggesting to change is adding [RoutePrefix("api/TestWebApi")] and [Route("GetFoo")] to the Controller and the Action, respectively? Or is there something else I'm missing? Because the attributes did not work, I'm getting the same behavior as before. – CarenRose Jul 23 '18 at 18:48
  • Please ensure you have configured attribute routing properly as indicated in the section "Enabling Attribute Routing" [here](https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2). – Ping Jul 25 '18 at 00:36
  • The `WebApiConfig.Register` has `config.MapHttpAttributeRoutes();` and `GlobalConfiguration.Configure(WebApiConfig.Register);` is correct in `Application_Start` – CarenRose Jul 25 '18 at 19:47
  • I am sorry that I cannot provide more help without seeing the details of your configuration. Please check [this question](https://stackoverflow.com/questions/19907226/asp-net-webapi-2-attribute-routing-not-working) and hope it helps. – Ping Jul 26 '18 at 00:42
  • I don't see anything in that question that is relevant to my issue. Attribute routing appears to be correctly configured though we are not using it in any of the other API Controllers in the project. – CarenRose Jul 26 '18 at 14:23