Web APi Routing Understanding - asp.net-mvc

I have created a new controller called WebPortalController but when I call it or try to call it via the browser I couldnt access the below method just said resource is not found. Do I need to add a new routing to the RoutesConfig.cs code if so how.?
namespace WebApi.Controllers
{
public class WebPortalController : ApiController
{
// GET api/webportal
private WebPortEnterpriseManagementDa _da = new WebPortEnterpriseManagementDa();
public ManagedType Get(string name)
{
ManagedType items = _da.GetManagedType(name);
return items;
}
// POST api/webportal
public void Post([FromBody]string value)
{
}
// PUT api/webportal/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/webportal/5
public void Delete(int id)
{
}
}
}
Routes file
namespace WebApi
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}

The route config you have shown is for MVC routes and is located in the App_Start/RouteConfig file. Check that you have a default API route set in your App_Start/WebApiConfig:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Then you will need to change the parameter name in your Get method to match the routing parameter:
public ManagedType Get(string id)
{
ManagedType items = _da.GetManagedType(name);
return items;
}
This should allow you to call your Get method through a browser using:
localhost:55304/api/WebPortal/Test
In order to test out your Post/Put/Delete methods you will need to use Fiddler or a browser addin such as Postman

Related

.Net Route Action Parameter coming back null despite being in url

UPDATE: It works fine is I add another parameter. I have no idea why.
Not sure what I am doing wrong, this route looks the same as the other routes, I've looked at all the other stackoverflow posts on the subject and everything looks up to snuff. Maybe someone can see something I can't?
Error: action parameter can't be null
The url: http://localhost:1319/EntryHistory/Entry/B2AAAA4A-B174-4C28-924F-A3B2027DD745
EntryHistoryController.cs:
public class EntryHistoryController : Controller
{
public ActionResult Entry(string entryId)
{
Guid parsedEntryId = Guid.Parse(entryId);
var history = new EntryHistoryService().BuildEntryHistoryViewModel(parsedEntryId);
return View(history);
}
}
RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
...
EntryHistoryRoutes(routes);
...
}
private static void EntryHistoryRoutes(RouteCollection routes)
{
routes.MapRoute(
"revisionhistory",
"entryhistory/entry/{entryId}",
new
{
controller = "entryhistory",
action = "entry",
entryId = UrlParameter.Optional
}
);
}
add attribute routing
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
...... your routes
//convention-based routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
and action
[Route("~/entryhistory/entry/{entryId}")]
public ActionResult Entry(string entryId)

MVC 5 Web Attribute Routing is not working

I implemented the Attribute routing in my Application and after that when I started nothing was working as planned. Only the Json Results works rest is not working as expected.
[RoutePrefix("ProductCategory")]
public class CategoryController : Controller
{
[Route("CategoryMain")]
// GET: /Category/
public ActionResult Index()
{
var cat = categoryService.GetCategories();
if (Request.IsAjaxRequest())
{
return PartialView("Index", cat);
}
return View("Index", cat);
}
}
Error
Server Error in '/' Application. The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its
dependencies) could have been removed, had its name changed, or is
temporarily unavailable. Please review the following URL and make
sure that it is spelled correctly.
Requested URL: /ProductCategory/MainIndex
I've also tried with Just Index even that is not working now
But if The method is JsonResult it will return me the data in json format. Its not working on any other ActionResults
My RouteConfig
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Category", action = "Index", id = UrlParameter.Optional }
);
}
My webapiConfig
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
My Global
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Autofac and Automapper configurations
Bootstrapper.Run();
Given the route prefix and route below
[RoutePrefix("ProductCategory")]
public class CategoryController : Controller {
[HttpGet]
[Route("CategoryMain")] // Matches GET ProductCategory/CategoryMain
public ActionResult Index() {
var cat = categoryService.GetCategories();
if (Request.IsAjaxRequest()) {
return PartialView("Index", cat);
}
return View("Index", cat);
}
}
The requested URL needs to be
ProductCategory/CategoryMain
for the CategoryController.Index Action

MVC.NET Routing

I want to add a new route to my Web Api, which will read various ids and then filter a bunch of books.
So the final url should read something like http://localhost/api/books/1/1/1/1
Now I have added a route to my RouteConfig as follows :-
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "BookFilter",
url: "api/books/{author}/{title}/{genre}/{isbn}",
defaults: new { controller = "Books", action = "BookFilter" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
I also added the following in my BooksController:-
[HttpGet]
public IQueryable<BookDTO> BookFilter(int authorId, int titleId, int genreId, int isbn)
{
//filter books here
return db.Books.ProjectTo<BookDTO>();
}
However when I try to reach the page, I get a 404.
What do I need to do to reach my page?
Thanks for your help and time
Web API and MVC are independent frameworks which each have separate types. The likely reason your route is not working is that you are confusing the two. Specifically, for it to work as you configured, you would need an MVC controller (that is, a controller that inherits System.Web.Mvc.Controller).
So, assuming you want to go with Web API as your question would indicate, you first need to ensure the correct definition of your controller. It should inherit from System.Web.Http.ApiController.
public class BooksController : ApiController
{
[HttpGet]
public IHttpActionResult BookFilter(string author, string title, string genre, string isbn)
{
return Ok("Successful result");
}
}
Next, you need to put your routing in the WebApiConfig.cs file, not in the RouteConfig.cs file. Don't forget to remove your route from the RouteConfig.cs file.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "BookFilter",
routeTemplate: "api/books/{author}/{title}/{genre}/{isbn}",
defaults: new { controller = "Books", action = "BookFilter" });
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
You also need to ensure that the call to GlobalConfiguration.Configure(WebApiConfig.Register); is in your application startup path (by default in Global.asax).
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Make sure to use the same parameter name in your action (eg. change author to authorId):
Optionally, you can also specify default values for these parameters at your RouteConfig, as follows:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "BookFilter",
url: "api/books/{authorId}/{titleId}/{genreId}/{isbn}",
defaults: new { controller = "Books", action = "BookFilter", authorId= UrlParameter.Optional, titleId = UrlParameter.Optional, genreId = UrlParameter.Optional, isbn = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Controller:
[HttpGet]
public IQueryable<BookDTO> BookFilter(int authorId, int titleId, int genreId, int isbn)
{
//filter books here
return db.Books.ProjectTo<BookDTO>();
}

Web api different named actions cause Multiple actions error

I have web api 2 controller actions:
[HttpGet]
public Response<IEnumerable<Product>> Get()
{
....(Get all products)
}
[HttpGet]
public Response<Product> Get(int id)
{
....(Get product by id)
}
[HttpGet]
public Response<IEnumerable<Product>> Category(int id)
{
.... (Get products by category)
}
I want to use this controllers with url:
http://localhost/api/product
http://localhost/api/product/1
http://localhost/api/product/category/1
But this url http://localhost/api/product/1 returns error,
Multiple actions were found that match the request
My config settings are like this:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApiWithAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
You might be better off using attribute routing rather than global routing here. If you remove your global routes and define your routes on a per-action basis you should have no problems. For example, your routes could look like:
[Route("api/product")]
[Route("api/product/{id:int}")]
[Route("api/product/category/{id:int}")]
This is the default controller created when you create a new ASP.NET Web APi within Visual Studio:
[Authorize]
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
And the WebApi config:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Your two Get methods match the same route. I would delete the first Get method and change your second Get method to use an optional id parameter like so:
[HttpGet]
public Response<IEnumerable<Product>> Get(int? id)
{
// Get all products if id is null, else get product by id and return as a list with one element
}
This way, Get will match routes for both "product" and "product/1".

WebAPI MVC Areas with same controller name

The structure of webapi is as follows:
App
-Area
-MyArea1
- ControllerA (Route('api/myarea1/controllera'))
-MyArea2
- ControllerA (Route('api/myarea2/controllera'))
Problem is that the route api/myarea1/controllera and api/myarea2/controllera are not being resolved. It comes are 404.
I read somewhere we need to implement IHttpControllerSelector but not sure what is the simplest way to implement this. If there is any other way it can be done?
Any idea.
Edit:
RouteConfig.cs
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Edit 2:
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapHttpRoute(
name : "MyArea1_default",
routeTemplate : "MyArea1{controller}/{action}/{id}",
defaults : new { action = "Index", id = UrlParameter.Optional }
);
}
If you want to use controllers with the same name, you need to specify the namespace for each route configuration.
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapHttpRoute(
name : "MyArea1_default",
routeTemplate : "MyArea1{controller}/{action}/{id}",
defaults : new { action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Your.Controller.Namespace.Here" }
);
}
For your reference:
http://haacked.com/archive/2010/01/12/ambiguous-controller-names.aspx/

Resources