I am writing a REST API in .net core. I am trying to test the API using Postman and I am getting an error saying
Failed to load resource: the server responded with a status of 404 ()
I know this error occurs when the route does not match. Not sure, what am I doing wrong with the route. Below is my code with the Route at the top:
namespace RecLoad.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class RecLoadPrimeController : ControllerBase
{
[Route("RecLoadPrime/insertRecLoadData/{RecStartDate}/{RecEndDate}")]
[HttpPost]
public void insertRecLoadData(string RecStartDate, string RecEndDate)
{
RecLoadDataProvider dataProvider = new RecLoadDataProvider();
dataProvider.InsertCardsData(RecStartDate, RecEndDate);
}
}
}
The URL that I am trying to test in Postman is below:
https://localhost:44360/api/RecLoadPrime/insertRecLoadData/?RecStartDate=01/01/2020&RecEndDate=01/02/2020
I am very new to API, this is the first API that I am writing. Below is the image for application structure. Its extremely simple:
Any help will be greatly appreciated.
A 404 error means not found. This means Postman cant find the end point you are trying to hit.
Your [Route] attribute needs to be updated. The root of this endpoint (controller) it's RecLoadPrime. So get rid of that part. If you are just trying to test, update it to [Route("insert")].
Using ? in your URL means you are passing query parameters. Which are usually used on GET requests not on POST requests.
Web API expects you to use Model Binding for passing in parameters. Meaning map the post parameters to a strongly typed .NET object, not to single parameters. Alternatively, you can also accept a FormDataCollection parameter on your API method to get a name value collection of all POSTed values.
For example: Create a small class called Card, with the properties startDate, and endDate. Make them DateTime. Now use that in the method signature public void insertRecLoadData([FromBody]Card card)
In Postman, you are now going to use the Body option and create a JSON representation of this new class we created.
For example: { "startDate": "2020-03-23", "endDate": "2020-03-27" }
In the route, you are going to use: POST | https://localhost:44360/api/insertRecLoadData/insert
Make sure you set breakpoints in your controller. Not sure how you have setup your project but I'd suggest reading up more on how to setup a Web API using ASP.NET Core. Look into RESTful design to also get an idea on how to best setup these end points.
Good luck!
The current route configuration on your controller and on your action will result in duplicated section in your route. Specifically, the route the action will be associated with will be "api/RecLoadPrime/RecLoadPrime/insertRecLoadData/{RecStartDate}/{RecEndDate}".
Consider removing the RecLoadPrim/ prefix from your action route attribute as follows:
[Route("insertRecLoadData/{RecStartDate}/{RecEndDate}")]
I have an OData controller with standard verbs for CRUD. Everything is working fine. Now I need to add a custom action to perform file upload. I try to add a method to my existing controller like this:
[HttpPost]
[Route("UploadFile")]
public async Task<HttpResponseMessage> UploadFile()
{
//handle uploaded content logic here...
}
But when I try to invoke it by doing a POST:
http://localhost/UploadFile
I get this error:
System.InvalidOperationException: No non-OData HTTP route registered.
What should I do for this custom action to allow file upload?
You need to declare the Action as part of the EdmModel, in the following example I am assuming that your Entity Type is Attachment, and your controller class name is AttachmentsController. By convention, your EntitySet name must then be Attachments
var attachments = builder.EntitySet<Attachment>("Attachments");
attachments.Action(nameof(AttachmentsController.UploadFile))
.Returns<System.Net.Http.HttpResponseMessage>();
The important part of the above statement is the return type, if you do not declare the return type correctly in your EdmModel then you will find your endpoints returning 406 errors - Unacceptable, even though your method executes correctly, which is really confusing the first time you run into it. This is because OData will still try to parse your response to match the Accept header from the request before completing the response.
Try to use 'nameof' when mapping functions and actions instead of 'magic strings' or constants so that the compiler can pickup basic issues like wrongly defined route.
With this approach you do not need the Route attribute on the method header and the action will be included in the metadata document and therefore swagger outputs.
I am struggling with the OData WebApi way to configure routing - mostly by not being able to get any sensible debugging information.
The API in question is part of a server service (as in: windows service) and as such OWIN based.
I have for example the following function:
function = builder.Function("MktSessions").ReturnsCollection<MktSession>();
function.Parameter<string>("Symbol");
function.Parameter<DateTimeOffset>("Begin");
function.Parameter<DateTimeOffset>("End");
and the controller has the following signature function:
[HttpGet]
[ODataRoute("MktSessions(Symbol={symbol},Begin={begin},End={end}")]
public IEnumerable<Reflexo.Api.MktSession> MktSessions (string symbol, DateTime begin, DateTime end) {
SOMETHING is wrong here. As long as the ODataRouter attbribute is presend, any call to $metadata resunlts in:
An error has occurred.
The object has not yet been initialized. Ensure that
HttpConfiguration.EnsureInitialized() is called in the application's
startup code after all other initialization code.
System.InvalidOperationException
at
System.Web.OData.Routing.Conventions.AttributeRoutingConvention.get_AttributeMappings()
at
System.Web.OData.Routing.Conventions.AttributeRoutingConvention.SelectController(ODataPath
odataPath, HttpRequestMessage request) at
System.Web.OData.Routing.ODataPathRouteConstraint.SelectControllerName(ODataPath
path, HttpRequestMessage request) at
System.Web.OData.Routing.ODataPathRouteConstraint.Match(HttpRequestMessage
request, IHttpRoute route, String parameterName, IDictionary`2 values,
HttpRouteDirection routeDirection) at
System.Web.Http.Routing.HttpRoute.ProcessConstraint(HttpRequestMessage
request, Object constraint, String parameterName,
HttpRouteValueDictionary values, HttpRouteDirection routeDirection) at
System.Web.Http.Routing.HttpRoute.ProcessConstraints(HttpRequestMessage
request, HttpRouteValueDictionary values, HttpRouteDirection
routeDirection) at
System.Web.Http.Routing.HttpRoute.GetRouteData(String virtualPathRoot,
HttpRequestMessage request) at
System.Web.Http.HttpRouteCollection.GetRouteData(HttpRequestMessage
request) at
System.Web.Http.Dispatcher.HttpRoutingDispatcher.SendAsync(HttpRequestMessage
request, CancellationToken cancellationToken) at
System.Net.Http.DelegatingHandler.SendAsync(HttpRequestMessage
request, CancellationToken cancellationToken) at
System.Web.Http.HttpServer.d__0.MoveNext()
which is as useless as it gets as an error message. I never have a chance to see original exception and this one jsut tells me the config is not there - which has no direct resemblence of the original error.
If I remove the ODataRoute attribute it works - but I can obviously not call the function.
Is there any way I am overlooking to actually get a meaningfull error message from this? Obviously the ODataRoute is somewhere in error (anyone knows where?) and a sensible "Parameter name blablbla does not match" text somewhere would be really helpfull.
There are two issues with the code your paste,
1. In the ODataRoute, you miss ")" after "{end}"
2. You should have define MktSessions as entity set, so your unbound function route can not be same as an entity set, you can change it to something else like RetrieveMktSessions as EntitySet query is enable by get method in controller but not a unbound function.
Let us know if you have any more issues.
Answering myself.
Now, on the side question there is a missing ")" at the end of the template.
More important, though.
When I add a call to HttpConfiguration.EnsureInitialized() to the end of the Owin configuration then I get the exception thrown there. This exception - while not having an inner exception - contains a meaningfull message that is lost in the web page output. This allows much better debugging.
I'm presently working on a project that has been upgraded to Webapi2 from Webapi. Part of the conversion includes the switch to using attribute based routing.
I've appropriately setup my routes in the Global.asax (as follows)
GlobalConfiguration.Configure(config => config.MapHttpAttributeRoutes());
and removed the previous routing configuration.
I have decorated all of my API controllers with the appropriate System.Web.Http.RouteAttribute and System.Web.Http.RoutePrefixAttribute attributes.
If I inspect System.Web.Http.GlobalConfiguration.Configuration.Routes with the debugger I can see that all my expected routes are registered in the collection. Likewise the appropriate routes are available within the included generated Webapi Help Page documentation as expected.
Even though all appears to be setup properly a good number of my REST calls result in a 404 not found response from the server.
I've found some notable similarities specific to GET methods (this is all I've tested so far)
If a method accepts 0 parameters it will fail
If a route overrides the prefix it will fail
If a method takes a string parameter it is likely to succeed
return type seems to have no affect
Naming a route seems to have no affect
Ordering a route seems to have no affect
Renaming the underlying method seems to have no affect
Worth noting is that my API controllers appear in a separate area, but given that some routes do work I don't expect this to be the issue at hand.
Example of non-functional method call
[RoutePrefix("api/postman")]
public class PostmanApiController : ApiController
{
...
[HttpGet]
[Route("all", Name = "GetPostmanCollection")]
[ResponseType(typeof (PostmanCollectionGet))]
public IHttpActionResult GetPostmanCollection()
{
return Ok(...);
}
...
}
I expect this to be available via http://[application-root]/api/postman/all
Interestingly enough a call to
Url.Link("GetPostmanCollection", null)
will return the above expected url
A very similar example of method calls within the same controller where some work and some do not.
[RoutePrefix("api/machine")]
public class MachineApiController : ApiController
{
...
[HttpGet]
[Route("byowner/{owner}", Name = "GetPostmanCollection")]
public IEnumerable<string> GetByOwner([FromUri] string owner)
{
...
}
...
[HttpGet]
[Route("~/api/oses/{osType}")]
public IEnumerable<OsAndVersionGet> GetOSes([FromUri] string osType)
{
...
}
...
}
Where a call to http://[application-root]/api/machineby/ownername succeeds and http://[application-root]/api/oses/osType does not.
I've been poking at this far too long, any idea as to what the issue may be?
Check that you configure your HttpConfiguration via the MapHttpAttributeRoutes method before any ASP.NET MVC routing registration.
In accordance to Microsoft's CodePlex entry on Attribute Routing in MVC and Web API the Design section states:
In most cases, MapHttpAttributeRoutes or MapMvcAttributeRoutes will be
called first so that attribute routes are registered before the global
routes (and therefore get a chance to supersede global routes).
Requests to attribute routed controllers would also be filtered to
only those that originated from an attribute route.
Therefore, within the Global.asax (or where registering routes) it is appropriate to call:
GlobalConfiguration.Configure(c => c.MapHttpAttributeRoutes()); // http routes
RouteTable.Routes.MapRoute(...); // mvc routes
In my case it was a stupid mistake, I am posting this so people behind me making the same mistake may read this before they check everything else at quantum level.
My mistake was, my controller's name did not end with the word Controller.
Happy new year
I've installed Visual Studio 2013 and when I run my app I get the error below.
I've got no idea as to where I'm to initialized this object.
What to do?
Server Error in '/' Application.
The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.]
System.Web.Http.Routing.RouteCollectionRoute.get_SubRoutes() +101
System.Web.Http.Routing.RouteCollectionRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request) +63
System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext) +107
System.Web.Routing.RouteCollection.GetRouteData(HttpContextBase httpContext) +233
System.Web.Routing.UrlRoutingModule.PostResolveRequestCache(HttpContextBase context) +60
System.Web.Routing.UrlRoutingModule.OnApplicationPostResolveRequestCache(Object sender, EventArgs e) +82
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.18408
This is for AlumCloud
If you do it at the end of Application_Start it will be too late, as WebApiConfig.Register has been called.
The best way to resolve this is to use new initialization method by replacing in Global.asax :
WebApiConfig.Register(GlobalConfiguration.Configuration);
by
GlobalConfiguration.Configure(WebApiConfig.Register);
See #gentiane's answer below for the correct way to handle this now.
At the end of the Application_Start method in Global.Asax.cs try adding:-
GlobalConfiguration.Configuration.EnsureInitialized();
I actually got this error when I was using Attribute Routing within my WebApi.
I had
[Route("webapi/siteTypes/{siteTypeId"]
instead of
[Route("webapi/siteTypes/{siteTypeId}"]
for my route and got this error. I had simply missed out the closing curly bracket. Once I added it back in, this error didn't occur again.
This is old, but is the first result on google when searching for this error. After quite a bit of digging I was able to figure out what was going on.
tldr:
All GlobalConfiguration.Configure does is invoke your action and call EnsureInitialized(). config.MapAttributeRoutes() must be called before EnsureInitialized() since EnsureInitialized only runs once.
Meaning: if you're coming from an existing Mvc project, all you have to do is:
Add
GlobalConfiguration.Configuration.EnsureInitialized();
to the bottom of your Application_Start method.
OR
Move your entire configuration into a single call to GlobalConfiguration.Configure:
GlobalConfiguration.Configure(config =>
{
WebApiConfig.Register(config);
config.MapAttributeRoutes();
...
});
Digging Deeper
HttpConfiguration.Configuration has an "Initializer" property defined like this:
public Action<HttpConfiguration> Initializer;
HttpConfiguration.EnsureInitialized() runs this action and sets _initialized to true
public void EnsureInitialized()
{
if (_initialized)
{
return;
}
_initialized = true;
Initializer(this);
}
HttpConfiguration.MapAttributeRoutes calls internal method AttributeRoutingMapper.MapAttributeRoutes which sets HttpConfiguration.Initializer
public static void MapAttributeRoutes(...)
{
RouteCollectionRoute aggregateRoute = new RouteCollectionRoute();
configuration.Routes.Add(AttributeRouteName, aggregateRoute);
...
Action<HttpConfiguration> previousInitializer = configuration.Initializer;
configuration.Initializer = config =>
{
previousInitializer(config);
...
};
}
GlobalConfiguration.Configure runs EnsureInitialized immediately after invoking your action:
public static void Configure(Action<HttpConfiguration> configurationCallback)
{
if (configurationCallback == null)
{
throw new ArgumentNullException("configurationCallback");
}
configurationCallback.Invoke(Configuration);
Configuration.EnsureInitialized();
}
Don't forget, if you run in to a wall, the source for asp.net is available at http://aspnetwebstack.codeplex.com/SourceControl/latest
I've had a related issue. Sometimes calling GlobalConfiguration.Configure multiple times triggers this error. As a workaround, I've put all configuration initialization logic in one place.
IF THIS ERROR SEEMS TO HAVE COME "OUT OF NOWHERE", i.e. your app was working perfectly fine for a while, ask yourself: Did I add an action to a controller or change any routes prior to seeing this error?
If the answer is yes (and it probably is), you likely made a mistake in the process. Incorrect formatting, copy/pasting an action and forgetting to make sure the endpoint names are unique, etc. will all end you up here. The suggestion that this error makes on how to resolve it can send you barking up the wrong tree.
For me, the problem was that I was trying to use named parameters for query string fields in my routes:
[Route("my-route?field={field}")]
public void MyRoute([FromUri] string field)
{
}
Query string fields are automatically mapped to parameters and aren't actually part of the route definition. This works:
[Route("my-route")]
public void MyRoute([FromUri] string field)
{
}
Although the above answer works if incase that is not set, In my case this stuff was set already. What was different was that, for one of the APIs I had written, I had prefixed the route with a / . Example
[Route("/api/abc/{client}")]
.Changing this to
[Route("api/abc/{client}")]
fixed it for me
Call
GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
before
GlobalConfiguration.Configure(c => ...);
completes its execution.
I got this error when the version of Newtonsoft.Json was different in my main project compared to the helper project
One typically gets this exception when route templates in "Attribute Routing" are not proper.
For example, i got this when i wrote the following code:
[Route("{dirName:string}/contents")] //incorrect
public HttpResponseMessage GetDirContents(string dirName) { ... }
In route constraints syntax {parameter:constraint}, constraint by default is of type string. No need to mention it explicitly.
[Route("{dirName}/contents")] //correct
public HttpResponseMessage GetDirContents(string dirName) { ... }
I began getting this error one day. After I'd altered our app to call EnsureInitialized() I was able to see the root cause.
I had a custom attribute, a filter, on an action. That attribute class had had a breaking change made in the NuGet package in which it lives.
Even though I'd updated the the code and it all compiled, the local IIS worker was loading an old DLL and not finding a class member during initialization, reading attributes on actions etc.
For some reason (possibly due to order/when our logging is initialized), this error was not discoverable, possibly leaving the WebAPI in a strange state, until I'd added EnsureInitialized() which caught the exception and surfaced it.
Performing a proper bin and obj clean via a handy script resolved it.
In my case I created the webservice in project A and started it from Project B and I got exactly this error. The problem was that some .dll-files which are required by A where missing in the build-output-folder of B. Ensure that these .dll-files are available fixed it.
In my case , i used an Entity as parameter of my action that its 'Schema' is missing.
Wrong attribute:
[Table("Table name", Schema = "")]
Correct :
[Table("Table name", Schema = "schema name")]
In my case I fixed replacing:
<Route("{id:string}")>
with
<Route("{id}")>
Strange that I was sure that the original code was working before suddenly stopping, go figure....
I experienced this similar error.
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>The object has not yet been initialized. Ensure that HttpConfiguration.EnsureInitialized() is called in the application's startup code after all other initialization code.</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace> at System.Web.Http.Routing.RouteCollectionRoute.get_SubRoutes() at System.Web.Http.Routing.RouteCollectionRoute.GetRouteData(String virtualPathRoot, HttpRequestMessage request) at System.Web.Http.WebHost.Routing.HttpWebRoute.GetRouteData(HttpContextBase httpContext)</StackTrace>
</Error>
After fiddling with it for a while, I realized two problems: directory name collides with routing prefix and routing prefix must not end with '/'. When starting up the service for debugging I got this browser error after adding the SampleController.cs.
The folder structure
/api/Controllers/SampleController.cs
/api/Model/...
SampleController.cs
[RoutePrefix("api/sub/{parameterId}/more/")]
public class SampleController : ApiController
{
[HttpGet]
[Route("")]
public IHttpActionResult Get(int parameterId)
{
return Ok("Knock Knock...");
}
}
Changing the routing prefix to not end in '/' and not colliding with the directory name solved the problem.