ASP.net MVC - Use Model Binder without query string values or fancy routes

送分小仙女□ 提交于 2019-12-06 10:31:57

You could use a custom value provider with a catchall route:

routes.MapRoute(
    "NoQueryString",
    "NoQueryString/{controller}/{action}/{*catch-em-all}",
    new { controller = "Home", action = "Index" }
);

and the value provider:

public class MyCustomProvider : ValueProviderFactory
{
    public override IValueProvider GetValueProvider(ControllerContext controllerContext)
    {
        var value = controllerContext.RouteData.Values["catch-em-all"] as string;
        var backingStore = new Dictionary<string, object>();
        if (!string.IsNullOrEmpty(value))
        {
            var nvc = HttpUtility.ParseQueryString(value);
            foreach (string key in nvc)
            {
                backingStore.Add(key, nvc[key]);
            }
        }
        return new DictionaryValueProvider<object>(
            backingStore, 
            CultureInfo.CurrentCulture
        );
    }
}

which you register in Application_Start:

ValueProviderFactories.Factories.Add(new MyCustomProvider());

and now all that's left is a model:

public class MyViewModel
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
    public string D { get; set; }
    public string E { get; set; }
}

and a controller:

public class HomeController : Controller
{
    [ValidateInput(false)]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

and then navigate to: NoQueryString/Home/Index/a=hello&b=world&c=1&d=2&e=3. The Index is hit and the model is bound.

Remark: Notice the ValidateInput(false) on the controller action. That's probably gonna be needed because ASP.NET won't allow you to use special characters such as & as part of a URI. You might also need to tweak your web.config a little:

<httpRuntime requestValidationMode="2.0" requestPathInvalidCharacters=""/>

For more information about those tweaks make sure you have read Scott Hansleman's blog post.

Whats the problem with "complex" routing definitions? The routes the question you linked to are very very simple. Defaults can go a long way. Better to use the default capabilities of MVC to turn:

example.com/Controller/Action/a=hello&b=world&c=1&d=2&e=3

into

example.com/Controller/Action/hello/world/1/2/3

than start re-wiring core bits like RouteValue handling ( option 1 ) or implementing a custom model binder.

I know this doesn't answer your question but it seems like you made a choice about not using MVC's routing capabilities without understanding the technical ramifications. You know what they say "good friends stop each other from doing stupid things".

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!