2

I have a asp.net MVC 5 project with lots of controllers and web apis. The problem is when i want to access one of the api methods, i get No HTTP resource was found that matches the request URI ... error.

I tried every solution in similar posts but i wasn't lucky. This is my RouteConfig file:

public static void Register(HttpConfiguration config)
{
    // Routing configs
    config.MapHttpAttributeRoutes();

    // Files api routs
    config.Routes.MapHttpRoute(
        name: "filesApi_1",
        routeTemplate: "api/{controller}/{action}/{file}",
        defaults: new object[]
        {
            new { controller = "Files", action ="SaveAttachment"}
        }
     );

config.Routes.MapHttpRoute(
    name: "filesApi_2",
    routeTemplate: "api/{controller}/{action}/{fileName}",
    defaults:
        new { controller = "Files", action = "DeleteAttachment" }
    );
}

When i go to htt://localhost:xxxx/api/Files/DeleteAttachment/file_name, i get the error.

My Global.asax.cs is:

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        GlobalConfiguration.Configure(WebApiConfig.Register); 
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        Mapper.Initialize(c=> c.AddProfile<MappingProfile>());
    }

The controller is:

public class FilesController : ApiController
{
    public void SaveAttachment(HttpPostedFileBase file){}
    public void DeleteAttachment(string fileName){}
}

It is very strange that if i add attribute routing for web api actions, they work as expected. For example:

[Route("api/Files/DeleteAttachment/{fileName}")]
public void DeleteAttachment(string fileName){}

I don't want write Route for every action because i have lots of actions and it make the code fragile. How can i fix routing in the route table? Thanks.

Ehsan Toghian
  • 548
  • 1
  • 6
  • 26

3 Answers3

2

Tag your Api controller methods with attributes [HttpGet] or [HttpPost] so the routing mechanism will know when to use each.

public class FilesController : ApiController
{
    [HttpPost]
    public void SaveAttachment(HttpPostedFileBase file){}
    [HttpGet]
    public void DeleteAttachment(string fileName){}
}


----------------------------------------------------------------------------------
And the second issue may be with your default routing values:

config.Routes.MapHttpRoute(
    name: "filesApi_2",
    routeTemplate: "api/{controller}/{action}/{fileName}",
    defaults:
        new { controller = "Files", action = "DeleteAttachment" }
    );

There is fileName parameter missing in default route, so change it to:

config.Routes.MapHttpRoute(
    name: "filesApi_2",
    routeTemplate: "api/{controller}/{action}/{fileName}",
    defaults:
        new { controller = "Files", action = "DeleteAttachment", fileName = "" }
    );

or

config.Routes.MapHttpRoute(
    name: "filesApi_2",
    routeTemplate: "api/{controller}/{action}/{fileName}",
    defaults:
        new { controller = "Files", action = "DeleteAttachment", fileName = RouteParameter.Optional }
    );


----------------------------------------------------------------------------------
Ok, if it is still not working than it is due to file_name containing .. Web api routing doesn't like dot characters in last parameter.

Change your URL from http://localhost:58893/api/files/deleteattachment/file.jpg
to
http://localhost:58893/api/files/deleteattachment/file.jpg/
and you should be able to invoke requested method

Tomas Chabada
  • 2,869
  • 1
  • 17
  • 18
1

You have to check the file name. If the file url is coming or the value in filename contain '/' it will split the route and create a new url as

htt://localhost:xxxx/api/Files/DeleteAttachment/file_name_before_slash/file_name_after_slash

It will not match your URL.

Check value in file name part of your code.

------------------- Edit 1 ------------------------------------

The problem may be in filename "file.jpg". The dot (.) in the file name causes the issue refer to this link, more similar questions are available. Also check this one.

try

 <configuration>
     <system.web>
         <httpRuntime relaxedUrlToFileSystemMapping="true"/>

          <!-- ... your other settings ... -->
     </system.web>
 </configuration>
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Jinto Jacob
  • 385
  • 2
  • 17
  • when there is not '/' in the file name, i can't reach the action too. – Ehsan Toghian Jun 26 '18 at 07:53
  • @ehsantoghian can you provide some more details about the error. like complete error message or stack trace. – Jinto Jacob Jun 26 '18 at 09:11
  • The complete error is: `{ "message": "No HTTP resource was found that matches the request URI 'http://localhost:58893/api/files/deleteattachment/file.jpg'.", "messageDetail": "No action was found on the controller 'Files' that matches the request." ` – Ehsan Toghian Jun 26 '18 at 09:45
  • @ehsantoghian the problem is in filename "file.jpg" the (.) in the file name causes the issue [reffer this link](https://stackoverflow.com/questions/11728846/dots-in-url-causes-404-with-asp-net-mvc-and-iis), more similar questions are available. [Also check this one](https://haacked.com/archive/2010/04/29/allowing-reserved-filenames-in-URLs.aspx/) – Jinto Jacob Jun 26 '18 at 09:59
  • i fixed the dot (.) in the file name, but for the brevity didn't mentioned that – Ehsan Toghian Jun 26 '18 at 10:29
1

Convention routing follows template based routing that you configure in webApiConfig but Attribute routing is a lot more flexible. I agree that you may not want to write [Route] attribute over every method but later provides a lot of flexibility.

In one of my project, I could use the same controller to have different route APIs serving similar functionality and as asked by UI development team.Refer this article

Praveen
  • 26
  • 1
  • 3