I am getting really weird routing issues when calling actions in my APIController. I have a WebApp, but needed an APIController so I added that as well as WebAPIConfig.cs to App_start and Global.asax.
However, when I try to call different Actions inside the APIController, it seems to not differentiate between the Actions unless I add a parameter. For example, if I call api/controller/happy it enters the same Action as api/controller/sad. It enters the Action that was created first in the Controller.
It makes no sense to me, the Action-names are not being considered in the URL.
my API Controller:
public class RegistrationManagerController : ApiController
{
EventHelper eh = new EventHelper();
[HttpGet]
public IHttpActionResult IsUserRegistered(string skypeid)
{
var skypeuser = Exist.CheckIfRegistered(skypeid);
return Ok(skypeuser);
}
[HttpGet]
public async Task<IHttpActionResult> Happy()
{
var events = await eh.GetHappyRecent();
return Ok(events);
}
[HttpGet]
public async Task<IHttpActionResult> Sad()
{
var events = await eh.GetSadRecent();
return Ok(events);
}
[HttpPost]
public async Task<IHttpActionResult> UpdateEvent() //TODO id send in body?
{
await eh.Update("id");
return Ok();
}
}
My WebAPIConfig.cs:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
My RouteConfig (This is a webapp, not a web API):
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();// New feature
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
Routetemplate should be
routeTemplate: "api/{controller}/{action}/{id}"
WebApi follows REST principals so it doesn't route the same way an MVC Controller routes.
Check out this answer here I think it will help you
need route for my web api 2 controller
Related
As Atrribute routing does not work in sitecore 8.1 out of the box, I am following https://github.com/Krusen/Sitecore.WebApi
And got the uget package for Krusen.Sitecore.WebApi.Custom.
This is my ConfigureWebApi class
public class ConfigureWebApi
{
public void Process(PipelineArgs args)
{
GlobalConfiguration.Configure(config => config.Routes.MapHttpRoute(
name: "myApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
));
GlobalConfiguration.Configure(config => config.MapHttpAttributeRoutes());
GlobalConfiguration.Configure(ReplaceControllerSelector);
}
private static void ReplaceControllerSelector(HttpConfiguration config)
{
config.Services.Replace(typeof (IHttpControllerSelector),
new CustomHttpControllerSelector(config, new NamespaceQualifiedUniqueNameGenerator()));
}
}
And this is my controller
[RoutePrefix("windows")]
public class WmsController : ApiController
{
[HttpGet]
[Route("hi")]
public IHttpActionResult Hello()
{
return Ok("Welcome to my Api.");
}
}
When I call this:
http://my.api.local/api/wms/hello
works.
But when I call
http://my.api.local/api/windows/hi
does not work. It says 404.
Am I missing something !!
The second call is not working because Attribute routing must be configured before Convention-based routes to avoid route conflicts.
public void Process(PipelineArgs args) {
GlobalConfiguration.Configure(config => {
// Map Attribute Routes
config.MapHttpAttributeRoutes();
// Map Convention-based Routes
config.Routes.MapHttpRoute(
name: "myApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// Replace IHttpControllerSelector with our custom implementation
ReplaceControllerSelector(config);
});
}
Which I also believe is how it was shown in the documentation in the linked repo
Secondly based on the RoutePrefix("window") and Route("hi") in the ApiController the mapped attribute route would be mapped as
http://my.api.local/windows/hi
To get http://my.api.local/api/windows/hi to map to the desired action you would need to update the route prefix as already explained in one of the other answers.
You need to add "api/" into your controller attribute routing
[RoutePrefix("api/windows")]
public class WmsController : ApiController
{
[HttpGet]
[Route("hi")]
public IHttpActionResult Hello()
{
return Ok("Welcome to my Api.");
}
}
I've gone over all stack over flow QAs and online tutorials, to add a Web API to my current MVC project.
The Web API works, the MVC works only if I put the routing path into the url.
I want the MVC routing to come up as default, but for some reason it always tries to do the API logic.
I'm hoping its something simple I've missed
What I have done so far.
Web API Config class
Default, not really changed anything
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
MVC config class
Default, not really changed anything
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 }
);
}
}
Global Config class
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
API Controller class
Default, not really changed anything
public class RegistrationController : ApiController
{
// GET: api/Registration
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET: api/Registration/5
public string Get(int id)
{
return "value";
}
MVC home Controller class
Default, not really changed anything
namespace MVCPortal.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}}
This is the error I'm getting
I am trying to write a self hosted WebAPI server. I want all routes to go to a single controller. This controller can pick out the controller part of the url and use this to decide an appropriate response.
I have the following route configuration:
_configuration.Routes.MapHttpRoute
(
name: "DefaultApi",
routeTemplate: string.Concat("api/Home", "/{id}"),
defaults: new { id = RouteParameter.Optional, controllerName="Home" }
);
My controller class is called "HomeController". I'm trying to redirect all URLs to it.
Here is the code for HomeController. For now I have commented out the calls to external logic (remote controller). It should just be returning a string on the Get action.
public class HomeController : ApiController
{
private IExternalController<string> remoteController;
public HomeController()
{
remoteController = GlobalKernelConfiguration.GetStandardKernel().Get<IExternalController<string>>();
}
public string Get()
{
return "HELLO FROM INTERNAL"; //remoteController.Get();
}
public string Get(int id)
{
return remoteController.Get(id);
}
public void Delete(int id)
{
remoteController.Delete(id);
}
public void Post(string value)
{
remoteController.Post(value);
}
public void Put(int id, string value)
{
remoteController.Put(id, value);
}
}
I would expect http://localhost:9000/api/[AnythingHere] to route to the home controller but I get the following error when trying the following url: http://localhost:9000/api/Home
{"Message":"No HTTP resource was found that matches the request URI 'http://loca
lhost:9000/api/Home'.","MessageDetail":"No route providing a controller name was
found to match request URI 'http://localhost:9000/api/Home'"}
As #CodeCaster suggested in the comments the problem was caused by not using the correct parameter in the routing options.
This is what I had before
_configuration.Routes.MapHttpRoute
(
name: "DefaultApi",
routeTemplate: string.Concat("api/Home", "/{id}"),
defaults: new { id = RouteParameter.Optional, controllerName="Home" }
);
this is what I have now:
public static void AddControllerRoute(string controllerName)
{
_configuration.Routes.MapHttpRoute
(
name: "DefaultApi",
routeTemplate: string.Concat("api/Home", "/{id}"),
defaults: new { id = RouteParameter.Optional, controller ="Home" }
);
}
notice that the defaults parameter was changed and now uses "controller" instead of "controllerName" this solved the problem and it's now working.
I have my MVC 4 Project API Routing configured as follow:
WebApiConfig.cs:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var company = System.Configuration.ConfigurationManager.AppSettings["DbCompany"];
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "MyApp/"+ company +"/{id}",
defaults: new { controller = "main" , id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
}
}
and MainController.cs contains the following methods:
public JToken Get(string id)
{
...
}
public JToken Get()
{
...
}
[HttpPost]
public JToken DoQuery([FromBody] String query)
{
...
}
public void Post([FromBody] JObject JsonObject)
{
...
}
What I would like to achieve is for any route that is not :
route: /MyApp/MyComp/DoQuery
method: POST
ContextType: text/plain
Returns: JToken
To use normal Get/Post of the main controller
Otherwise use DoQuery in the main controller.
Seems like all you are missing is the special case route to map to DoQuery.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var company = System.Configuration.ConfigurationManager.AppSettings["DbCompany"];
config.Routes.MapHttpRoute(
name: "DoQuery",
routeTemplate: "MyApp/"+ company +"/DoQuery",
defaults: new { controller = "main", action = "DoQuery" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "MyApp/"+ company +"/{id}",
defaults: new { controller = "main" , id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
}
}
I'm making a call to http://localhost/AppTools.WebAPI/api/BulletinBoard/GetMessagesForApp/AppName, but it's returning a 404 error. I think this has to do with routing, but I'm not sure.
Here's the Web API method inside my BulletinBoard controller:
[HttpGet]
public HttpResponseMessage GetMessagesForApp(string id)
{
// get current, valid messages
var messages = (from i in db.BulletinBoards
where i.AppId == id &&
DateTime.Today >= i.DisplayFrom &&
DateTime.Today <= i.DisplayTo &&
i.IsActive == true
select new
{
Message = i.Message,
IntervalId = i.IntervalId,
Interval = i.Interval.IntervalDescription,
Timeout = i.Timout,
})
.ToList();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, messages);
return response;
}
Here's my RouteConfig.cs:
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 standard Get() and Get(int id) work fine, I didn't change the method name or signatures. Get() returns a complete list of records, Get(int id) returns a specific record. I want GetMessagesByApp(string id) to return a list of records specific to a certain AppName. Can you tell why this isn't working?
Here's my RouteConfig.cs:
The RouteConfig.cs file is used to define the routes for your ASP.NET MVC controllers. Those have absolutely nothing to do with the routes used by your Web API controllers. They are defined in the WebApiConfig.cs file.
So make sure you have declared your routes in the proper place:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ApiWithActionName",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Notice that I have added a custom route before the default one which will allow you to achieve the desired url pattern.
And then you could have the following controller action which will work fine:
// GET /api/controllername
// GET /api/controllername/get
[HttpGet]
public HttpResponseMessage Get()
{
...
}
// GET /api/controllername/get/123
[HttpGet]
public HttpResponseMessage Get(int id)
{
...
}
// GET /api/controllername/GetMessagesForApp/abc
[HttpGet]
public HttpResponseMessage GetMessagesForApp(string id)
{
...
}