In a ASP.NET Web api project I have a VacationController where I want to use these action methods.
How can I construct the routes to achieve this?
public Enumerable<Vacation> GetVacation()
{
// Get all vactions
return vacations;
}
public Vacation GetVacation(int id)
{
// Get one vaction
return vacation;
}
public Enumerable<Vacation> ByThemeID(int themeID)
{
// Get all vactions by ThemeID
return vacations;
}
I would like the URL's to look like this
/api/vacation // All vacations
/api/vacation/5 // One vacation
/api/vacation/ByThemeID/5 // All vacations from one theme
Edit 30-10-2013
I have tried Pasit R routes but I can't getting to work. I verily tried every combination I could think of.
This is what I have know. As you can see I have added a extra parameter at the bein of the route. I realized that I needed that in order to seperate the Vacations sold onder different labels.
Here are the routes I use. and the work OK for these URL's
/api/vacation // All vacations
/api/vacation/5 // One vacation
/api/vacation/ByThemeID/5 // All vacations from one theme
But it dosn't work for the last URL
config.Routes.MapHttpRoute(
name: "DefaultApiSimbo",
routeTemplate: "api/{label}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
And here my Action method in the VacationController
// ByThemeID api/{label}/Vacation/ByThemeId/{id}
[HttpGet]
public IEnumerable<Vacation> ByThemeID(string label, int id)
{
return this.repository.Get(label);
}
// GET api/{label}/Vacation
public IEnumerable<Vacation> GetVacation(string label)
{
return repository.Get(label);
}
// GET api/{label}/Vacation/{id}
public Vacation GetVacation(string label, int id)
{
Vacation vacation;
if (!repository.TryGet(label, id, out vacation))
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
return vacation;
}
Can some one give my a push in the right direction ;-)
Thanks in advance
Anders Pedersen
Assuming that the class is name VacationController, then a default routes for these methods would look something like:
/api/Vacation/GetVacation
/api/Vacation/GetVacation?id=1
/api/Vacation/ByThemeID?id=1
This is all assuming that the routing has note been updated.
add defaults action = "GetVacation" and make id as optional
the ApiController base class could handle overload GetVacation() and GetVacation(int id) selection automatically.
to register WebApiConfig
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{*param}",
defaults: new { action = "Get", param = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "Vacation",
routeTemplate: "api/vacation/{action}/{*id}",
defaults: new { controller = "Vacation", action = "GetVacation", id = RouteParameter.Optional }
);
}
Related
I've added this method to my web api controller:
[HttpPost]
public bool CreateTrening(int routineId)
{
try
{
var userId = User.Identity.GetUserId();
TreningService.CheckIfLastTrenigWasCompleted(userId);
TreningService.CreateTreningForUser(userId, routineId);
return true;
}
catch (Exception ex)
{
return false;
}
}
And I've added another route to my WebApiConfig file, so it looks like this now:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "CustomApi",
routeTemplate: "{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
But when I try to call my method:
/EditWorkout/CreateTrening/1
I get this error:
{"Message":"No HTTP resource was found that matches the request URI '/EditWorkout/CreateTrening/1'.","MessageDetail":"No action was found on the controller 'EditWorkout' that matches the request."}
How can I call my method which is in WebApi controller ?
Calling with that URL to a post method will not work because the post expects the values transmitted in the Http Message body. not in the URL so your controller is not finding the method.
Probably the best solution for this is to encode your posted value in the http message you send the controller, and call the URL with /EditWorkout/CreateTrening, this will work as a post.
Here is another SO thread where the question of how to do this was answered,
Specific post question answered
I'm having a problem with MVC 4, and I guess it's something really trivial, but it's been bugging me for the last day and I can't seem to figure it out.
I have this url:
http://www.example.com/my-dashed-url
I have a Controller named:
public class MyDashedUrlController: Controller
{
}
I have only two Routes like this:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("my-dashed-url",
"my-dashed-url/{action}",
new { controller = "MyDashedUrl", action = "Index" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home",
action = "Index",
id = UrlParameter.Optional }
);
I get to the index just fine. However, when I do this:
public ActionResult Index()
{
if (NoUserIsLoggedOn)
return RedirectToAction("Logon", "MyDashedUrl");
return View();
}
public ActionResult Logon()
{
Contact c = GetContact();
return View(c);
}
It doesn't redirect me to the "Logon" action properly.
It should redirect me to:
http://www.example.com/my-dashed-url/logon
but instead it tries to redirect me to:
http://www.example.com/logon
... which doesn't work (404 Not Found)
I'm missing something. Can anyone spot it? If anyone needs any more information, let me know.
And it's EVERY RedirectToAction that does the same thing in this controller. A Html.BeginForm("Logon", "MyDashedUrl") would also generate:
http://www.example.com/logon
I guess it has to do something with the Routes I defined, but I can't find the faulty one, seeing as they're all the same. If I disable all of my Routes besides the default one from MVC, the problem remains the same
Make sure that you have declared this custom route BEFORE the default one:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"my-dashed-url",
"my-dashed-url/{action}",
new { controller = "MyDashedUrl", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Remember that routes are evaluated in the order you declared them. So the first route that matches a request will be used. If you declare your custom route after the default one, it is the default route that will match the request.
I've tried to step through this extensively and could not find the answer. There are about 30 methods defined that all map correctly but this single method does not. It differs because it has 3 params while the others do not.
[HttpGet]
public Info<List<SEOJobTitleLocation>> GetSeoTopLocations(string jobTitle, string city = "", string state = "")
{
return _jobs.GetSeoTopLocations(jobTitle, city, state);
}
and the Areas code is as follows:
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.MapHttpRoute(
name: "AreaApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { area = AreaName, id = RouteParameter.Optional },
constraints: new { id = #"^\d+$" }
);
context.Routes.MapHttpRoute(
name: "AreaApiWithAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { area = AreaName, action = "get", id = RouteParameter.Optional }
);
}
I've gone as far as downloading the symbols from Microsoft to step through the build and could see this particular method is not being generated in the code. I have absolutely no clue as to why. Sorry I cannot give more info than that.
The specific error message I get is as follows:
No HTTP resource was found that matches the request URI...
Thank you for looking into this in advance.
Try removing the two optional parameters and "defaulting" those inside the function, just as a test to see if it will instantiate the function.
I am creating my first ASP.NET web API. I am trying to follow the standard REST URLs. My API would return the search result records. My URL should be –
../api/categories/{categoryId}/subcategories/{subCategoryId}/records?SearchCriteria
I am planning to use oData for searching and Basic / Digest Authentication over IIS. My problem is in the nested resources. Before I return the search results, I need to check whether the user has access to this category and sub category.
Now I created my Visual Studio 2012 – MVC4 / Web API project to start with. In the App_Start folder, there are 2 files that I believe are URL and order of resource related.
1.RouteConfig.cs
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
2.WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
With this model, it works fine if my URL is ../api/records?SearchCriteria but it is not my URL design mentioned above. I understand that I have to do little more reading but so far not able to find the correct article. Need your advice on how to achieve my URL and what changes are needed in these 2 files. Alternatively, are there some other configuration that I am missing here? Thanks in advance.
Asp.net Web API 2 provides Attribute routing out of the box. You can define Route on individual action method or at global level.
E.g:
[Route("customers/{customerId}/orders/{orderId}")]
public Order GetOrderByCustomer(int customerId, int orderId) { ... }
You can also set a common prefix for an entire controller by using the [RoutePrefix] attribute:
[RoutePrefix("api/books")]
public class BooksController : ApiController
{
// GET api/books
[Route("")]
public IEnumerable<Book> Get() { ... }
// GET api/books/5
[Route("{id:int}")]
public Book Get(int id) { ... }
}
You can visit this link for more information on Attribute routing in Web API 2.
Assuming you have a controller named categories, Your WebApiConfig.cs could have a route like this to match your desired url (I would personally leave the /records portion off):
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{categoryId}/subcategories/{subCategoryId}",
defaults: new { controller = "categories", categoryId = somedefaultcategory,
subCategoryId = RouteParameter.Optional }
);
and a method could look like this:
// search a single subcategory
public IQueryable<SearchRecord> Get(int categoryId, int subCategoryId = 0, string SearchCriteria = "")
{
// test subCategoryId for non-default value to return records for a single
// subcategory; otherwise, return records for all subcategories
if (subCategoryId != default(int))
{
}
}
But, what if you want to also return just the categories and not subcategories? You'd need an additional route after the first one that is more generic:
config.Routes.MapHttpRoute(
name: "Categories",
routeTemplate: "api/{controller}/{categoryId}",
defaults: new { controller = "categories", categoryId = RouteParameter.Optional }
);
with two methods like:
// search a single category
public IQueryable<SearchRecord> Get(int categoryId, string SearchCriteria = "")
{
}
// search all categories
public IQueryable<SearchRecord> Get(string SearchCriteria = "")
{
}
I have two methods in my Web API controller as follows:
public samplecontroller: webapicontroller
{
[HttpPost]
public void PostMethod()
[HttpGet]
public void GetValues(int a,int b)
}
I have the following in global.asax:
routes.MapHttpRoute
("Default API Route", "api/{controller}/{id1}/{id2}/{id3}/{id4}/{id5}",
new { id1 = UrlParameter.Optional, id2 = UrlParameter.Optional, id3 = UrlParameter.Optional, id4 = UrlParameter.Optional, id5 = UrlParameter.Optional });
If I want to call the second method i.e., GetValues(int a,int b), can I write one more HttpRoute in Global.asax as follows?
routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{Sample}/{GetValues}/{a}/{b}",
defaults: new { a = UrlParameter.Optional, b=UrlParameter.Optional }
);
So can I create more than one maproute in global.asax?
And, to provide the optional parameter, should I give the same as parameters like a and b only?
You can have multiple routes in global.asax; each incoming request will go to the first route that matches. That means that the more specific ones should go first. A URL matches a route if:
the controller and action route values are defined.
All required route values (both ones in the curly brackets in the route, as well as non-nullable parameters in the Action) are defined.
That said, your proposed route api/{Sample}/{GetValues}/{a}/{b} doesn't make sense. It creates two new (meaningless) route values Sample and GetValues, and doesn't provide a definition controller or action. I think what you meant to write is this:
routeTemplate: "api/Sample/GetValues/{a}/{b}",
defaults: new { controller: "Sample", action: "GetValues", a = UrlParameter.Optional ,b=UrlParameter.Optional }
This will match the URI /api/Sample/GetValues/1/2 to your action.
routeTemplate: "api/Sample/GetValues/{a}/{b}",
defaults: new { controller: "Sample", action: "GetValues", a = UrlParameter.Optional ,b=UrlParameter.Optional }