In a self hosted webapi console application project, I am not able to hit the SayHello method using http://localhost:9998/api/shri/flows/config.
Error:
{
"Message": "No HTTP resource was found that matches the request URI 'http://localhost:9998/api/shri/flows/config'.",
"MessageDetail": "No route data was found for this request."
}
Controller:
class ConfigController : ApiController
{
[HttpGet, Route("{id}/flows/config")]
public string SayHello([FromUri] string id)
{
return "Hello " + id;
}
}
Startup:
public class Startup
{
// This code configures Web API. The Startup class is specified as a type
// parameter in the WebApp.Start method.
public void Configuration(IAppBuilder appBuilder)
{
// Configure Web API for self-host.
HttpConfiguration config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
appBuilder.UseWebApi(config);
}
}
To keep the self hosted webapi running I have the following:
public class Program
{
static void Main()
{
Uri myUri = new Uri(#"http://localhost:9998/");
// Let have our configurations readY
HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(myUri);
// configure routes
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
HttpSelfHostServer server = new HttpSelfHostServer(config);
// Start listening
server.OpenAsync().Wait();
Console.WriteLine("WebApi hosted on " + myUri.AbsoluteUri + " It can be tested now");
Console.ReadLine();
}
}
What am I missing?
Change route
[HttpGet,Route("api/{id}/flows/config")]
With such routing your action will be accessible by http://localhost:9998/shri/flows/config url (without /api part)
If you want to access that action with http://localhost:9998/api/shri/flows/config url either correct Route attribute for the action:
[HttpGet, Route("api/{id}/flows/config")]
public string SayHello([FromUri] string id)
or add RoutePrefix attribute on controller class:
[RoutePrefix("api")]
public class ConfigController : ApiController
For someone in the future that might be struggling with this, as Nkosi said you need to enable attribute routing.
public class Program
{
static void Main()
{
Uri myUri = new Uri(#"http://localhost:9998/");
// Let have our configurations readY
HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(myUri);
// enables the attribute routing
config.MapHttpAttributeRoutes();
// configure routes
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
HttpSelfHostServer server = new HttpSelfHostServer(config);
// Start listening
server.OpenAsync().Wait();
Console.WriteLine("WebApi hosted on " + myUri.AbsoluteUri + " It can be
tested now");
Console.ReadLine();
}
}
If attribute routing is not configured then it does not matter if your routing is correct, When the request is made to the API it will not get the parameter values from the address itself even if you use [FromBody] or [FromUri].
I hope this helps someone, It was the issue in my case.
Related
I am new to MVC and C#, so sorry if this question seems too basic.
I have trouble with calling 'action' in web api.
I don't know why my method below always throws an error:
"No HTTP resource was found that matches the request URI 'https://localhost:44358/api/RollUp/TrainingImage".
While other methods ([HttpGet]) run normally
public class RollUpController : ApiController
{
.
.
. orther method
[HttpPost]
public string TrainingImage(string name)
{
return name;
}
}
This is the file webApiConfig.cs:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
This is the result when I test it by PostMan : test by postman
When i am hitting the url:
http://localhost/api/adxxx/getDeals/?input=2
I get the following error:
"Message": "No HTTP resource was found that matches the request URI
'http://localhost/api/adxxx/getDeals/?input=2'.",
"MessageDetail": "No type was found that matches the controller
named 'adxxx'."
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.DependencyResolver = new UnityResolver(UnityBootstrapper.Initialise());
config.EnableCors();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "xxx.services",
routeTemplate: "webapi/{controller}/{action}"
);
config.Routes.MapHttpRoute(
name: "xxx.services_new",
routeTemplate: "api/{controller}/{action}",
defaults: new { id = RouteParameter.Optional }
);
FluentValidationModelValidatorProvider.Configure(config);
}
}
[Route("api/adxxx/getDeals/")]
public IHttpActionResult GetDeals(int input)
{
//code here
}
How do i resolve this? Very similar apis having different route are working fine.
This happened when i have added fluent validation to my api. That updated my System.Web.Http.dll to v5.2.3.0
Correct your route config for allow parameter
[Route("api/adxxx/getDeals/{input}")]
public IHttpActionResult GetDeals(int input)
{
//code here
}
and then you can request it by
http://localhost/api/adxxx/getDeals/2
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'm getting crazy with this.
I'm developing an ASP.NET Web Api 2.2 project with Visual Studio 2012 Premium, .NET Framework 4.5.1 and C#.
I have created an empty ASP.NET MVC 5 project. I have deleted Global.asax and create this Startup.cs class:
using Microsoft.Owin;
using Ninject;
using Ninject.Web.Common.OwinHost;
using Ninject.Web.WebApi.OwinHost;
using Owin;
using System.Reflection;
using System.Web.Http;
using System.Web.Routing;
using MyProject.Web.API.App_Start;
[assembly: OwinStartup(typeof(MyProject.Web.API.Startup))]
namespace MyProject.Web.API
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
var webApiConfiguration = new HttpConfiguration();
webApiConfiguration.Routes.MapHttpRoute(
name: "Default",
routeTemplate: "{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
webApiConfiguration.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
webApiConfiguration.Routes.MapHttpRoute(
name: "ProductionOrderActionApi",
routeTemplate: "api/MyProductionOrders/{orderNumber}/{action}",
defaults: new { controller = "MyProductionOrders" });
app.UseNinjectMiddleware(CreateKernel);
app.UseNinjectWebApi(webApiConfiguration);
}
private static StandardKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
RegisterServices(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
var containerConfigurator = new NinjectConfigurator();
containerConfigurator.Configure(kernel);
}
}
}
The project works fine with ApiController classes, but when I try to access to a Controller I get HTTP 404 Status code: not found.
What do I have to do to allow Web pages? I think the problem is with Routes but I have tried to add RouteConfig to the project, but I don't know how.
I have searched a lot on Google but I haven't found anything related to my question (or maybe I haven't put the correct search term).
If you need NinjectConfigurator class, please tell me and I add it.
You need to use MapRoute for Controllers.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
MapRoute is an extension method and within that the MvcRouteHandler is setup as the route handler for the request. If you haven't mapped a given route to be handled by MvcRouteHandler then you're not engaging the Mvc request processing pipeline that leads to a controller being instantiated.
MapRoute uses an MvcRouteHandler
public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
if (routes == null)
throw new ArgumentNullException("routes");
if (url == null)
throw new ArgumentNullException("url");
Route route = new Route(url, (IRouteHandler) new MvcRouteHandler())
{
Defaults = RouteCollectionExtensions.CreateRouteValueDictionaryUncached(defaults),
Constraints = RouteCollectionExtensions.CreateRouteValueDictionaryUncached(constraints),
DataTokens = new RouteValueDictionary()
};
ConstraintValidation.Validate(route);
if (namespaces != null && namespaces.Length > 0)
route.DataTokens["Namespaces"] = (object) namespaces;
routes.Add(name, (RouteBase) route);
return route;
}
MapHttpRoute uses an HttpMessageHandler:
public static IHttpRoute MapHttpRoute(this HttpRouteCollection routes, string name, string routeTemplate, object defaults, object constraints, HttpMessageHandler handler)
{
if (routes == null)
throw Error.ArgumentNull("routes");
HttpRouteValueDictionary routeValueDictionary1 = new HttpRouteValueDictionary(defaults);
HttpRouteValueDictionary routeValueDictionary2 = new HttpRouteValueDictionary(constraints);
IHttpRoute route = routes.CreateRoute(routeTemplate, (IDictionary<string, object>) routeValueDictionary1, (IDictionary<string, object>) routeValueDictionary2, (IDictionary<string, object>) null, handler);
routes.Add(name, route);
return route;
}
To me it indeed looks like the routing setup has not been set as you only defined the routes for webapi. The routing configuration for mvc and webapi is a little bit different so you can't setup the routing for both in the way you did there.
A quote from book i am reading:
The key to avoiding conflict between the frameworks is a careful route
setup; to facilitate that, by default ASP.NET Web API will occupy URI
space under /api, while all of the other root-level URLs will be
handled by MVC. Typically Web API routes are defined in the
WebApiConfig static class against the HttpConfiguration object and its
Route property, while MVC routes are defined in the static RouteConfig
class, directly against the System.Web.RouteCollection.
//Web API routing configuration
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 routing configuration
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 }
);
}
}
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 }
);