Routing to different WebAPI controller's action where optional route param exists - c#

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"));
}
}

Related

c# Asp.net Web API Attribute Routing 404 Error

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)
{
...
}

ASP.net Web API 2 block route in area on root

I have a route defined in an area, have set the configuration up and routes are firing as expected, however, I can hit the area routes on the root profile as well.
Is there a way to block the root profile from seeing my area routes (defined only in the area only), something like this:
/area/api/awesomeservice -> only this one should be allowed
/api/awesomeservice -> should not be allowed
RouteConfig.cs:
public class 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 = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "TestBed.Controllers" }
);
}
}
WebApiConfig.cs:
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 }
);
}
Service controller under /Areas/Services
ServiceController.cs
namespace TestBed.Areas.Services.Controllers
{
public class HotFuzzController : ApiController
{
[HttpGet]
public string Get()
{
return "Hello World";
}
}
}
Area configuration for Areas/Services
ServicesAreaRegistration.cs
namespace TestBed.Areas.Services
{
public class ServicesAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Services";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.Routes.MapHttpRoute(
name: "ServicesApiAction",
routeTemplate: "services/api/{controller}/{action}");
context.Routes.MapHttpRoute(
name: "ServicesApi",
routeTemplate: "services/api/{controller}");
context.MapRoute(
"Services_default",
"Services/{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] { "TestBed.Areas.Services.Controllers" }
);
}
}
}
Global.asax.cs
namespace TestBed
{
public class WebApiApplication : 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);
}
}
}
The problem comes from the default route that matches the areas controllers. Unfortunately there is no way in the framework (that I know of) to make a route only for controllers that are not in an area.
But you can make a custom RouteContraint and apply your own matching rules. Here is an example of a route constraint that uses reflection to match only controllers of the executing assembly that are in namespaces :
public class NamespaceFilterConstraint : System.Web.Http.Routing.IHttpRouteConstraint
{
private Type[] types;
public string[] AllowedNamespaces { get; }
public NamespaceFilterConstraint(string[] ns)
{
AllowedNamespaces = ns;
types = Assembly.GetExecutingAssembly().GetTypes();
}
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName, IDictionary<string, object> values, HttpRouteDirection routeDirection)
{
var controllerName = values["controller"] + "Controller";
//This assumes no controllers with the same name in different namespaces
Type controllerType = types.FirstOrDefault(t => t.Name == controllerName);
return AllowedNamespaces.Contains(controllerType.Namespace);
}
}
You can use it in the WebApiConfig :
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: new { controller = new NamespaceFilterConstraint(new string[] { "MyApp.Controllers" }) }
);

Web api route values is empty on action executes filter

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.

Not differentiating between Action names in url Path - asp.net web api

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

Attribute Routing gives 404 for api/delete/1

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 }
);

Categories

Resources