ASP.NET Core Model Binding to force the prefix on complex types

Viewed 637

Given a model:

public class MyModel
{
    public MyModel()
    {
    }

    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}

and a controller action:

public async Task<IActionResult> MyAction(MyModel myModel) {}

how to achieve model binding behavior such that this binds properly:

www.host.blah/page?MyModel.Prop1=a&MyModel.Prop2=b

and this doesn't bind (without a prefix):

www.host.blah/page?Prop1=a&Prop2=b

I'm not sure of the correct terminology, but judging from Model Binding in ASP.NET Core:

For each property of the complex type, model binding looks through the sources for the name pattern prefix.property_name. If nothing is found, it looks for just property_name without the prefix.

but I want to avoid that default fallback without the prefix.

If it's relevant at all, I'm trying to accomplish this since the controller in question can be embedded in other controllers/pages, as a sub-tab in UI, so I can't control which other query string parameters will exist at that point.

1 Answers

Try the OnPageHandlerSelected method to manipulate the query string that executes before the model is selected. You can register it globally and use it across the app.

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Http.Extensions;

public override void OnPageHandlerSelected(PageHandlerSelectedContext context)
{
    //...
    var querystring = QueryHelpers.ParseQuery(context.HttpContext.Request.QueryString.Value);
    var items = querystring.SelectMany(x => x.Value, (col, value) => new KeyValuePair<string, string>(col.Key, value)).ToList();
}

Alternatively, you can create your own model binder

Further Reading:

Related