简体   繁体   中英

Routing by posted content type in ASP.NET MVC

I have a fixedURL to which I'd like to post different types of xml message, deserialized using DataContracts. Depending on the type of the deserialized message, I'd like to route to: overloaded methods, eg

void Process(ContractType1 request) {}
void Process(ContractType2 request) {}

So at some point I need to deserialize this message and hopefully allow the default routing rules to match the correct method. Which extensibility point should I use for this? Or even better, can I make this work out of the box?!

If it makes any difference, I'm using MVC 3.

ASP NET MVC does not respect the overload if they are not decorated for different HTTP methods - eg one for POST , other for GET .

You need to use [ActionName(Name = "Process2")] to change the route name. And you will have to use different routes to access (if the HTTP methods are the same)

Have a look here .


Apart from the technical workaround, passing different contracts to the same URL is against the REST principles. Data could be in different format (XML, JSON, ...) but it must be the same. The URI defines a unique intention. Now it is possible to have a common dumpster where documents are all dumped to the same URI but then ASP NET MVC default model binder would not be able to help you and you need to create your own model binder .

Contrary to the other answer I say this is possible

Asp.net MVC is a great platform that can be easily extended. And so basically I've written a special action method selector that makes it possible to write overloads that can serve the same HTTP method but defer in parameters. By default you'd get runtime error that action method can't be resolved. But when you use this action method selector you get rid of this error.

Basically if your parameter classes have distinct parameter names, you can actually select methods by that.

Action method selector is called RequiresRouteValuesAttribute and a typical usage scenario would be with default route where id is optional in:

{controller}/{action}/{id}

This means that you either have to write

public ActionResult Index(int? id)
{
    if (id.HasValue)
    {
        // display details view
    }
    else
    {
        // display master view
    }
}

but by using my action method selector you can easily write two action methods:

public ActionResult Index()
{
    // display master view
}

[RequiresRouteValues("id")]
public ActionResult Index(int id)
{
    // display details view
}

The same could be applied to your action methods as long as your custom types have distinct property names or methods use different parameter names. So in your case it could be something like:

[RequiresRouteValues("first.Id")] // when you provide prefix with your form
// or
[RequiresRouteValues("Some.ContractType1.Distict.Property.Name")]
public ActionResult Process(ContractType1 first)
{
    // do what's appropriate
}

[RequiresRouteValues("second.Id")] // when you provide prefix with your form
// or
[RequiresRouteValues("Some.ContractType2.Distict.Property.Name")]
public ActionResult Process(ContractType2 second)
{
    // do what's appropriate
}

Read all the details about this action method selector and get the code as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM