Asp.net Web API Attribute Routing 404 Error - c#

I cannot figure out for the life of me why my attribute routing isn't working.
Here is my setup:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Attribute routing
config.MapHttpAttributeRoutes();
// Convention-based routing
config.Routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Here is my controller with my routing attributes:
[Route("api/v1.0/orders")]
public class OrdersV1Controller
{
[APIAuthentication(RequireAuthentication = true)]
[HttpGet]
[Route("{id:int}")]
public GetOrderResponse GetOrder(int id)
{
.....
}
}
Here is my global asax file:
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Populate;
}
}
Here is the URL i'm testing which is returning a 404 not found:
http://localhost:60105/api/v1.0/orders/111111

your controller needs to be an API Controller :
public class OrdersV1Controller : ApiController

Related

resource api not found in mvc application

In existing MVC application I have added api support.
Added api controller but when i hit url it shows error -
The resource cannot be found.
I tried url -
https://localhost:44316/api/getdata
https://localhost:44316/Test/api/getdata
TestController.cs
public class TestController : ApiController
{
[HttpGet]
[Route("api/getdata")]
public IEnumerable<string> GetData()
{
return new string[] { "value1", "value2" };
}
}
WebApiConfig.cs
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 }
);
}
}
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 }
);
}
}
If this is an existing MVC application, then you need to register your web api routes. You need to add this line of code to Global.asax.cs to register your web api routes in Application_Start method:
GlobalConfiguration.Configure(WebApiConfig.Register);
Once you do that, your URLs should then work.
The Route attribute is in wrong place, it should decorate the Controller class.
Try this:
[Route("api/[controller]")]
public class TestController : ApiController
{
[HttpGet]
public IEnumerable<string> GetData()
{
return new string[] { "value1", "value2" };
}
}
and call Get http://localhost:XXXX/api/test.

FluentValidation Doesn't Work When Using WebApi [Route] Attribute

I successfully implemented FluentValidation in my WebApi project controller that only had one HttpGet method. When I added another HttpGet method, I added route attribute to both methods. i.e. [Route("Method1")] and [Route("Method2")].
Now the ModelState comes back as true regardless of whether I enter any data or not.
Here is my code.
WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Filters.Add(new ValidateModelStateFilter());
//FluentValidation
FluentValidationModelValidatorProvider.Configure(config);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{action}/{id}",
defaults: new { controller = "Menu", id = RouteParameter.Optional}
);
}
}
ValidateModelStateFilter
public class ValidateModelStateFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
}
}
}
Controller
[HttpGet]
[Route("Method1")]
public IHttpActionResult ReadAllMenusByApplication([FromUri] ReadAllMenusByApplicationInput input)
{
var result = new List<ApplicationMenu>();
...
}
Input Object
using FluentValidation;
using FluentValidation.Attributes;
namespace MenuService.Models
{
[Validator(typeof(ReadAllMenusByApplicationInputValidator))]
public class ReadAllMenusByApplicationInput
{
public ReadAllMenusByApplicationInput() {
this.ApplicationName = string.Empty;
}
/// <summary>
/// The MenuSystem name of the application
/// </summary>
public string ApplicationName { get; set; }
}
public class ReadAllMenusByApplicationInputValidator : AbstractValidator<ReadAllMenusByApplicationInput>
{
public ReadAllMenusByApplicationInputValidator()
{
RuleFor(x => x.ApplicationName).NotEmpty();
}
}
}
Using this article for reference
Custom Validation in ASP.NET Web API with FluentValidation
You seem to have most of what is done in the referenced article.
Check your configuration order.
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Web API configuration and services
config.Filters.Add(new ValidateModelStateFilter());
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "{action}/{id}",
defaults: new { controller = "Menu", id = RouteParameter.Optional}
);
//FluentValidation
FluentValidationModelValidatorProvider.Configure(config);
}
}
FluentValidation automatically inserts its errors into the ModelState. You should include an error message.
public class ReadAllMenusByApplicationInputValidator : AbstractValidator<ReadAllMenusByApplicationInput> {
public ReadAllMenusByApplicationInputValidator() {
RuleFor(x => x.ApplicationName).NotEmpty()
.WithMessage("The Application Name cannot be blank.");
}
}
The article has some content that is outside of the scope of your question. mainly wrapping the responses but everything else should work for you.

CastleWindsor not working with route in asp.net mvc

I have a WebApplication in ASP.NET MVC using the dependency injection with CastleWindsor but when I add a route attribute, the application returns following error "The controller no found".
My ControllerInstaller
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<IController>()
.LifestyleTransient());
}
}
I have a following controller:
[Route("espetaculos")]
[FrontAuthorize]
public class EventController : Controller
{
#region DependencyInjection
private readonly IApplication applicationWeb;
private readonly IEventBusiness eventBusiness;
private readonly IShowBusiness showBusiness;
private readonly ISession sessionWeb;
private readonly ILog iLog;
public EventController(IEventBusiness eventBusiness, IShowBusiness showBusiness, IApplication applicationWeb, ISession sessionWeb, ILog iLog)
{
this.eventBusiness = eventBusiness;
this.showBusiness = showBusiness;
this.applicationWeb = applicationWeb;
this.sessionWeb = sessionWeb;
this.iLog = iLog;
}
when I access the route "/espetaculos" here is the error
The Castle expects only the full path of controller?
Edit
My RouteConfig class
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new { favicon = #"(.*/)?favicon.ico(/.*)?" });
//routes.MapMvcAttributeRoutes();
//AreaRegistration.RegisterAllAreas();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Plateia.Controllers" }
);
}
}
As I suspected, you apparently haven't enabled attribute routing in MVC. Without doing so, adding the [Route] attribute on your controllers and actions will have no effect.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{*favicon}", new { favicon = #"(.*/)?favicon.ico(/.*)?" });
// This line is required in order to scan
// for [Route] attribute in your controllers
routes.MapMvcAttributeRoutes();
//AreaRegistration.RegisterAllAreas();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "Plateia.Controllers" }
);
}
}

Assimilating WebApi Controller in MVC 5 Project

I am proficient in MVC 5 but web api 2 is new to me. I am trying to add a webapi controller to my MVC Project, But I can't access It's path.
Iv'e added a web api controller in a new Folder called webapi, and the name of the controller is searchcontroller, Inside My MVC 5 Project.
I can't access it's path, something that should be:
/api/search/get.
I think It might be with something with my App Start in Global Ajax :
Help Please!
Here is the code in the app start :
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(config =>
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ApiById",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: new { id = #"^[0-9]+$" }
);
config.Routes.MapHttpRoute(
name: "ApiByName",
routeTemplate: "api/{controller}/{action}/{name}",
defaults: null,
constraints: new { name = #"^[a-z]+$" }
);
config.Routes.MapHttpRoute(
name: "ApiByAction",
routeTemplate: "api/{controller}/{action}",
defaults: new { action = "Get" }
);
});
The controller code :
public class WebAPISearchReultsController : ApiController
{
public IEnumerable<ICE.Logic.ArticleSearchResult> Get(string searchQuery)
{
return SearchLogic.Instance.GetArticleSearchResults(searchQuery);
}
}
I would construct the API method like this...
[Route("api/webapisearchreults")]
[HttpGet]
public HttpResponseMessage Get([FromUri]string searchQuery)
{
var data = SearchLogic.Instance.GetArticleSearchResults(searchQuery);
var response = Request.CreateResponse(HttpStatusCode.OK, data);
return response;
}
You could then check the data and if there's no data or an exception etc you can inspect the HttpStatusCode returned. You can set the status code, to something meaningful.
EDIT: WebApiConfig
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}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

ASP.NET Web API returns code 404 with newly created ApiController

I just recently added a new ApiController to my ASP.NET MVC4 project (I already had one ApiController also in the Controllers folder) called ServerInfoController. I created this using the CRUD template option; here's what it looks like:
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebFrontend.Models;
namespace WebFrontend.Controllers
{
public class ServerInfoController : ApiController
{
// GET api/serverinfo
public Dictionary<string, string> Get()
{
var settings = GlobalStaticVars.StaticCore.LoadServerSettings("Last", "Server");
if (settings != null)
{
return new Dictionary<string, string>
{
{"ServerIP", settings.Address},
{"ServerPort", settings.Port.ToString()}
};
}
return new Dictionary<string, string>
{
{"ServerIP", ""},
{"ServerPort", ""}
};
}
}
}
However, every time that I attempt to navigate to that resource in the browser, I receive a 404 error. I know that my routes are registered correctly as my other controller is still reachable at the /api endpoint.
The following is the route that is configured in WebApiConfig.cs (it's the default route):
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
You don't need {action} part in the route. This is default routing:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}

Categories