2

When using web api, how does one call the proper routing methods if you use [RoutePrefix()]

Say you have something like "MyReallyLongNamedClassController". the default route would be http:...com/api/MyReallyLongNamedClass. The application then goes by methods named Get, Post, Put, etc (unless of course using verb decorators).

If I put a route prefix decorator of [RoutePrefix("api/LongClass")] on my controller, how can I have web api still use the defaults for the methods?

Meaning, I want the method named "GetAll()" to still map to "api/LongClass" (when using a get header) and "PostThis(int id)" to still map to "api/LongClass/{id}" (when using a post header)

0

3 Answers 3

6

Here's what I did to solve the problem without having to decorate all methods with annotations. I put RoutePrefix at the class level, as well as the default Route

[RoutePrefix("api/longclass")]
[Route("{id?}")]
public class MyReallyLongNamedClass: ApiController
{

    public string GetAll(int id)
    { 
        return "result";
    }


    public string PostThis([FromBody] MyModel model)
    {
       var res=  _repository.Save(model);
       return res;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Another option: if all you want to do is change the controller name in the route, you can create a custom controller selector:

public class CustomControllerSelector : DefaultHttpControllerSelector
{
    public CustomControllerSelector(HttpConfiguration configuration)
        : base(configuration)
    { }

    public override string GetControllerName(HttpRequestMessage request)
    {
        var name = base.GetControllerName(request);

        // Interpret "LongClass" as "MyReallyLongNamedClass"
        if (name == "LongClass")
            name = "MyReallyLongNamedClass";

        return name;
    }
}

Then you can register the controller selector in your WebApiConfig.Register:

config.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(config));

The advantage of this is that you can use your already-mapped routes (defined using HttpRouteCollection.MapHttpRoute()) instead of using attribute routing. However, if you need to use attribute routing for other reasons anyways, then your solution is probably better.

Comments

0

You don't have to worry about how the RoutePrefix attribute works internally. You can decorate either your controller or actions with RoutePrefix and can call the actions in accordance with your settings. You will have to use the Route atribute in your actions in order for [RoutePrefix] to work properly.

For example, in the below controller, all GET requests to url api/longclass/get will invoke the GetAll method and all POST requests to api/longclass/postwill invoke PostThis

[RoutePrefix("api/longclass")]
public class MyReallyLongNamedClass: ApiController
{
    [Route("get")]
    public string GetAll(int id)
    { 
        return "result";
    }

    [Route("post")] 
    public string PostThis([FromBody] MyModel model)
    {
       var res=  _repository.Save(model);
       return res;
    }
}

2 Comments

When I do that I get the following error {"Message":"No HTTP resource was found that matches the request URI 'localhost:26308/api/… type was found that matches the controller named 'longclass'."}
While I did not try your solution to see if it works, I did find another solution that works.I put [RoutePrefix("api/LongClass")] and [Route("{id?}")] at the controller level

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.