0

I have a action method which is called with parameters, one parameter is an int and another parameter to the action method is an Object.

When I inspect the action method I see that the Object parameter is not entirely null, the UserId property of this object is set to a value, e.g. model.UserId = 82

How do I stop ASP.NET from creating the Object? I could hack this by renaming the userId primitive variable to something like paramUserId, but is not ideal.

Here is the action method:

[HttpGet]
public async Task<IActionResult> Select(int userId = 0, ObjectModel model = null)

The url:

https://localhost:5001/[Area]/[Controller]/Select?userId=82

The ObjectModel:

   public class ObjectModel
   {
       public int Id { get; set; }
       public int UserId { get; set; }
   }
Wayne
  • 3,359
  • 3
  • 30
  • 50
  • What is this object model for? – ProgrammingLlama Nov 13 '19 at 02:02
  • @John some other action method redirects to this action method with an Object. All other calls I would want the model to be null; but it does not work this way; .NET is injecting an Object. – Wayne Nov 13 '19 at 02:09
  • 1
    It's been a while since I've dabbled in .NET MVC, but is the model you think is being injected actually a view model? In other words, is it being automatically created for use in the method's view in order to (potentially) display data to the screen? – Major Productions Nov 13 '19 at 02:13
  • Can you try to declare it explicitly as `[FromBody]`? If it works I'll add an answer. – ProgrammingLlama Nov 13 '19 at 02:14
  • @John Status Code: 415; Unsupported Media Type. – Wayne Nov 13 '19 at 02:19
  • I think that's to do with it being empty. [This question](https://stackoverflow.com/questions/44538772/asp-net-core-form-post-results-in-a-http-415-unsupported-media-type-response) might fix it. – ProgrammingLlama Nov 13 '19 at 02:23

1 Answers1

1

The complex models in the get request are passed in the format of the querystring, so when you call the https://localhost:5001/[Area]/[Controller]/Select?userId=82, the default model binding will automatically match the parameters for value binding (case insensitive).If you don't want to change the int type parameter name , you could try custom model binding that binds the model based on the upper/lower case of the UserId in the requestas follows :

MyCustomerModelBinder

public class MyCustomerModelBinder:IModelBinder
{
    public  Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)

        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var modelResult = new ObjectModel();

        //Get the Query in the request 
        var queryResult =new Dictionary<string, string>();
        var query = bindingContext.HttpContext.Request.Query;
        foreach (var k in query.Keys)
        {
            StringValues v = string.Empty;
            var flag = query.TryGetValue(k, out v);
            if (flag)
            {
                queryResult.Add(k, v);
            }
        }

        // Bind model when UserId exists in the Query
        if (queryResult.ContainsKey("UserId"))
        {
            modelResult.Id =Convert.ToInt32(bindingContext.ValueProvider.GetValue("id").FirstValue);
            modelResult.UserId =Convert.ToInt32(bindingContext.ValueProvider.GetValue("UserId").FirstValue);
            bindingContext.Result = ModelBindingResult.Success(modelResult);
            return Task.CompletedTask;
        }

        modelResult = null;
        bindingContext.Result = ModelBindingResult.Success(modelResult);
        return Task.CompletedTask;
    }
}

Action

[HttpGet]
    public async Task<IActionResult> Select(int userId = 0, [ModelBinder(BinderType = typeof(MyCustomerModelBinder))] ObjectModel model = null)
Xueli Chen
  • 11,987
  • 3
  • 25
  • 36