I cannot figure out why one my attribute routing isn't working, the first action method works but not the second one.
Here is my setup:
public class ActivMobileController : ApiController
{
[HttpGet]
[Route("api/ActivMobile/Impact/{token}")]
public IHttpActionResult Impact(string token)
{
...
}
[HttpGet]
[Route("api/ActivMobile/Attachments/{id}")]
public IHttpActionResult Attachments(string id)
{
...
}
}
here is my WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Reference: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
config.EnableCors(new EnableCorsAttribute(CloudConfigurationManager.GetSetting("AllowOrigins"), "*", "*"));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Here is the URL im testing and it gives 404 Error
http://localhost:60105/api/ActivMobile/Attachments/39E522838A652508112E9AD1E0E831C7
You're specifying API twice when it's already in your default template
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Remove the redundant Api/activMobile from your routes
[Route("Impact/{token}")]
public IHttpActionResult Impact(string token)
{
...
}
[HttpGet]
[Route("Attachments/{id}")]
public IHttpActionResult Attachments(string id)
{
...
}
Related
I am using a custom action filter on my controller action.
My controller action is like this:
[HttpPost]
[Route("listener")]
[MyAttr]
public IHttpActionResult Listener([FromBody]Parameters request)
{
return Ok();
}
I want to access Route("listener") values from action filter.
public class MyAttr: ActionFilterAttribute
{
public async override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
{
var route = actionExecutedContext.ActionContext.RequestContext.RouteData;
}
}
But RouteData values collection has no items. How can access route value?
My configuration is like this:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Please add /{action} in your WebApiConfig.cs file.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
api/ControllerName/Listener the link will to be that.
I have checked links related to mvc5, webapi2 but not being able to figure out my mistake.
My Problem:
/api/EBanking/CheckLogin is not excuting code of checkLogin method in ebankingcontroller
Links checked:
Custom Routing not working in MVC5
WebAPI2 and MVC5 route config
QueryString with MVC 5 AttributeRouting in Web API 2
App_start Code:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutoMapperCentralAppConfig.Configure();
}
RouteConfig.cs
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 string UrlPrefixRelative { get { return "~/api"; } }
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ActionBased",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
APi Controller:
[RoutePrefix("api/EBanking")]
public class EBankingController : ApiController
{
public EBankingController()
{
//some other code, it runs
}
[HttpGet, HttpPost]
[Route("CheckLogin")]
public IEnumerable<usr06user_role> CheckLogin(string UserName, string Password)
{
//main code which doesn;t runs
}
public IEnumerable<usr06user_role> GetAll()
{
//test code which runs when we call: /api/ebanking/
}
result screenshot:
In your WebApiConfig.cs add another route for action based routing like this:
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ActionBased",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
This "api/{controller}/{action}/{id}" will allow calls to api/ebanking/checklogin
Alternatively you can even add full route in attribute such as:
[Route("api/EBanking/CheckLogin")]
public IEnumerable<usr06user_role> CheckLogin(string UserName, string Password)
{
//main code which doesn;t runs
}
I've got a C# project using Web API. I've defined my prefix and routing for my controller, but I keep receiving an error when trying to access the "all" route:
{
"message": "No HTTP resource was found that matches the request URI '.../api/InventoryOnHand/all'.",
"messageDetail": "No type was found that matches the controller named 'InventoryOnHand'."
}
Here's my controller:
[RoutePrefix("api/inventoryonhand")]
public class InventoryOnHandController : ApiController
{
public InventoryOnHandController(){}
[HttpGet]
[Route("all")]
[CacheOutput(ClientTimeSpan = 50, MustRevalidate = true)]
public IHttpActionResult GetAllInventoryOnHand()
{
// Do stuff
}
}
My WebApiConfig isn't the issue (I think) because we have other routes working just fine, can't figure out why this one is the odd man out. Our routing in WebApiConfig:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
EDIT Adding the WebApiConfig file:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// require authenticated users in all controllers/action unless decoratd with "[AllowAnonymous]"
config.Filters.Add(new AuthorizeAttribute());
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
config.Services.Add(typeof(IExceptionLogger), new SerilogExceptionLogger());
ConfigureJsonHandling(config.Formatters.JsonFormatter);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// Web API routes
config.MapHttpAttributeRoutes();
}
private static void ConfigureJsonHandling(JsonMediaTypeFormatter json)
{
//make our json camelCase and not include NULL or default values
json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
json.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore;
json.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
}
EDIT Adding the Startup file (shortened for brevity):
public void Configuration(IAppBuilder app)
{
LoggingConfig.ConfigureLogger();
HttpConfiguration httpConfiguration = new HttpConfiguration();
var container = IoC.Initialize();
httpConfiguration.DependencyResolver = new StructureMapResolver(container);
ConfigAuth(app);
WebApiConfig.Register(httpConfiguration);
GlobalConfiguration.Configure(WebApiConfig.Register);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(httpConfiguration);
Log.Logger.ForContext<Startup>().Information("======= Starting Owin Application ======");
}
Since you are using attributes, you can't get routing by convention. In your WebApiConfig (where you have the route right now), you need to add a line to config.MapHttpAttributeRoutes() like this:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
The call to the MapHttpAttributeRoutes extension method is what will pick up the attributes for the route/routeprefix and create a new route to your method.
Attribute Routing in ASP.NET Web API 2
The order in which routes are mapped is important. Attribute route mapping config.MapHttpAttributeRoutes() must be done before convention-based routes because when the framework is matching routes in the route table, the first match wins. If a route is match via convention then it will not reach the attribute routes.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//..other code removed for brevity
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
ApiController
[RoutePrefix("api/inventoryonhand")]
public class InventoryOnHandController : ApiController {
public InventoryOnHandController(){}
//GET api/inventoryonhand
[HttpGet]
[Route("")]
[CacheOutput(ClientTimeSpan = 50, MustRevalidate = true)]
public IHttpActionResult GetAllInventoryOnHand() {
// Do stuff
}
}
Try this in the Startup.
public void Configuration(IAppBuilder app)
{
LoggingConfig.ConfigureLogger();
HttpConfiguration httpConfiguration = GlobalConfiguration.Configuration;
GlobalConfiguration.Configure(WebApiConfig.Register);
var container = IoC.Initialize();
httpConfiguration.DependencyResolver = new StructureMapResolver(container);
ConfigAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
Log.Logger.ForContext<Startup>().Information("======= Starting Owin Application ======");
}
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 am doing a SPA with web api as the backend and AngularJS as the SPA.
I am using attribute routing in WebApi2. The problem is when I do any http request that matches the following skeleton, it throws me a 404 NOT Found.
Request: http://localhost:63915/api/cab/delete/2
Request:
Error:
WebApiConfig Code:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
RouteDeclaration:
[RoutePrefix("api/driver")]
public class DriverController : ApiController
{
[POST("new")]
public bool NewDriver(DriverModel driver)
{
return new DatabaseService().CreateNewDriver(driver);
}
[GET("all")]
public List<DriverModel> GetAllDrivers()
{
return new DatabaseService().GetDriverList();
}
[DELETE("delete/{id}")]
public bool Delete(int id)
{
return new DatabaseService().DeleteDriver(id);
}
}
If I do something like api/driver/delete?id=2 and change the route to [DELETE("delete")] it works.
Is everything all right with my config ?
I think the problem might be with my config only. Please tell me what I am missing to make the route work.
I added another route to the WebApiConfig and it works!
config.Routes.MapHttpRoute(
name: "ComplexApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);