I have an API endpoint that shall export some data as an Excel xlsx file. The URL I try to get is like this: localhost/service/resources/123.xlsx (because I think using this extension is a nice way to do it).
But it always gives me a 404 Not Found.
The controller has a route prefix: [RoutePrefix("resources")] and the route attribute on the action is: [Route("{id:int}.xlsx")]
Even when I changed the route to [Route("123.xlsx")] it would not find it. I also tried a regex constraint [Route("{key:regex(\\d+\\.xlsx}")] with no luck.
I suspect it may be grabbed by static file handler, but the web config already has the setting
<modules runAllManagedModulesForAllRequests="true"/>
I believe this should work, because it worked for a very similar route in a previous project, using the old routing setup and not attribute routing. That project was not hosted using OWIN, but is that the problem here?
How can I make this work? I need this route for both GET and PUT.
Btw, localhost/service/resources/123 will return a different representation of the resource.
Info: Hosted in IIS 7.5 using OWIN 3.0 and Web API 5.2.2
I found out here that adding this line of code
app.UseStageMarker(PipelineStage.MapHandler);
after
app.UseWebApi()
in the Startup class made it work!
(I don't actually understand exactly what it does, but hey, who cares)
Related
I have a very basic Single Sign On app built on VS 2015 using MVC and Web Forms. It is supposed to be a simple proof of concept and is based on some code found here and here which are essentially the same things. I've finally gotten it all converted to use .Net 4.5 but when running it on my local server it throws a 404 with no debug information.
The 404 itself wasn't initially a surprise as I was supposed to be able to change the url to one of the secure pages (for instance /WebSecApp1) which would redirect me back to the signon page but no matter what I put as the url I get the 404.
I've also tried changing the urls in the code so that they contain the port numbers for the localhost but that doesn't work either.
It was suggested to me that the RouteConfig.cs could be the culprit but I don't see how that could be since I'm calling a single page with no parameters.
I know this is kind of lite on details but does anyone have any suggestions?
Yes this looks like a routing issue as you also thought it to be. Routing is essential for web api too .Pls see https://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection. Does your api request look like this
GET http://localhost:34701/api/products/1?version=1.5&details=1
You do have to mention the port in the request.
While the routing that Arathy mentioned above was partially to blame, the real problem turned out to be relatively simple. In my case simply selecting Properties->Web for each of offending pages and setting "Override application root URL" to checked fixed the whole problem.
I am using Elmah. I need to access axd extension file through the browser.
Since it is a Web-Api project, I need to register IgnoreRoute(*.asx).
I have done this at RouteConfig.cs as well as WebApiConfig.cs
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
I can understand that for API it will make no difference to set IgnoreRoute at RouteConfig level. However for WebapiConfig.cs I wrote this:
config.Routes.IgnoreRoute("elmmah", "{resource}.axd/{*pathInfo}");
It makes no difference whatsoever, and I cannot access elmah.axd
{"message":"No HTTP resource was found that matches the request URI 'http://x.com/api/elmah.axd'.","messageDetail":"No route data was found for this request."}
The moment I enter this at application , global asax it works!
So why these three areas are different?
RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
An Insight question will be great!
I am using a WebForms application with some MVC components added in. The idea is to move more and more of the app over to MVC but there is no way it can be transitioned all at once. For various reasons I cannot control it must use ASP.Net 2.0 and MVC 2.0 since those are what ship built-in. I must also support IIS 6 and IIS 7.
First, I am well aware of the problems with extensionless routing and I am not attempting to use it so there are no issues with wildcard mappings, etc. I first attempted to use my routes ala "{controller}.aspx/{action}/{id}" but after banging my head on the wall I switched to "{controller}.mvc/{action}/{id}" but am having the same issues.
Second, I cannot get this to work even in IIS 7 Integrated mode on my dev machine, let alone Classic mode or IIS 6. It all runs correctly under Cassini but once I deploy to IIS 7 the MVC components break. Since this is on my dev machine I know ASP.Net is registered with IIS correctly and I can see all the inherited HTTP handlers in the control panel (eg: ASPX maps to PageHandlerFactory).
Symptoms:
All ASPX WebForms requests work perfectly.
An MVC requests to just the controller with no action/id specified get routed to MVC and execute properly as well.
Any request to an MVC route with an action or id immediately returns a 404. It is as if IIS thinks the ".mvc" extension is part of the folder path so it ignores the HTTP handler and returns a 404.
In other words:
/app/WebForm.aspx - HTTP 200 OK, executes WebForm.aspx.cs code-behind
/app/Fancy.mvc - HTTP 200 OK, executes /Controllers/FancyController.cs, Index method
/app/Fancy.mvc/DoThingy - HTTP 404 NOT FOUND, even though FancyController has DoThingy method
Bad Solutions: I have tried things like setting runAllManagedModulesForAllRequests but not only is that bad for performance it also breaks my Web Forms as well. Even when I set it to ignore all routes with .ASPX in them they still break.
I cannot use wildcard mapping so that is no help.
Other Details:
I setup my HTTP Handler in web.config/system.WebServer. It is the first handler listed.
<add name="MvcRoutingHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Routing.UrlRoutingHandler, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" resourceType="Unspecified" />
It doesn't seem to matter what handler I specify or what options - IIS just doesn't seem to be examining any of this configuration (again because it seems to think the Fancy.mvc part of the path is a directory name, doesn't find that directory, then bails).
My routes:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");
routes.IgnoreRoute("{resource}.asmx/{*pathInfo}");
routes.IgnoreRoute("{resource}.aspq/{*pathInfo}");
routes.IgnoreRoute("{resource}.svc/{*pathInfo}");
routes.MapRoute("Default",
"{controller}.mvc/{action}/{id}",
new { action = "Index", id = UrlParameter.Optional }
);
Update: I tried using IIS 7 Classic mode; I then added a .mvc mapping in the IIS Manager pointing at the asp_net ISAPI dll and got the same result
OK just so others don't look foolish, it turns out that this was a problem with URLs... the URL was being sent to the root of the site, not the app directory. I should have checked that to begin with. I didn't think this was the problem because when I manually typed the URL into the address bar it worked on the Index but the action method required HttpPost, so it was a combination of factors that made the script and manually-entered addresses spit out the same error message.
For anyone else mixing WebForms and MVC, double and triple-check that your URLs are correct. Here is some code I am now using on the WebForms master page so my client-side JS can know where to route MVC requests:
string baseUrl = Request.Url.GetLeftPart(UriPartial.Authority);
if (baseUrl.EndsWith("/")) baseUrl = baseUrl.Substring(0, baseUrl.Length - 1);
baseUrl = baseUrl + ResolveUrl("~/");
Page.ClientScript.RegisterHiddenField("BaseUrl", baseUrl);
I my WebApplication I have an ASPX WebForms Page here:
~/ASPWebforms/MyFolder/Default.aspx
If I use this code:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapPageRoute(
"SomeRoute",
"Test/{reportname}",
"~/ASPWebforms/MyFolder/{reportname}.aspx"
);
and then enter this in the browser:
localhost/MySite/Test/Default
I get the desired the result: The page ~/ASPWebforms/MyFolder/Default.aspx is displayed.
But if I use the following
code
routes.MapPageRoute(
"SomeRoute",
"Test/",
"~/ASPWebforms/MyFolder/Default.aspx"
);
and try
localhost/MySite/Test
IIS 7.5 says:
HTTP Error 403.14 - Forbidden The Web server is configured to not list
the contents of this directory.
Do I do something wrong in the last piece of code?
Thx in advance!
I had something a lot like this, and from reading around it seems like it could be caused by several different things. In my case I had a route like this:
routes.MapPageRoute("signin", "signin", "~/SignIn/SignIn.aspx")
So the route path is /signin, but there is also a folder called /signin containing the .aspx page.
I got the error response
HTTP Error 403.14 - Forbidden. The Web server is configured to not list the contents of this directory.
This was fixed when I added this line to the route config:
routes.RouteExistingFiles = true;
The error message has a grain of truth in it: /signin is a directory, and the web server is configured to not list files in it. It seems that this file path takes precedence over the route unless you configure it otherwise.
Other things that I tried:
I did not need to use a different overload of MapPageRoute
I did not need to add UrlRoutingModule to the web.config under
system.webServer|Modules. It works without that.
It works without the web.config setting
<modules runAllManagedModulesForAllRequests="true">
I do have that for other reasons, but if I remove it then this fix still works.
I did install the server feature "Http Redirection" in the machine's Server Manager|Web
Server|Add Role Services dialogue but after removing it again this still works.
Reinstall .NET 4 x86 & x64 on IIS 7.5 and setup your web site .net version.
I write simple commands by default x86.
Stopping IIS:
1)iisreset /stop
Stup command(for iis by default .net stup):
2) cd %windir%\Microsoft.NET\Framework\v4.0.30319
3)aspnet_regiis.exe -i
Reset command(for iis by defalt .net change to .net 4 version):
4)aspnet_regiis.exe -iru
Starting IIS:
5)iisreset /start
Try setting up the route using one of the overloads that sets default values like so:
routes.MapPageRoute(
"SomeRoute",
"Test/{reportname}",
"~/ASPWebforms/MyFolder/{reportname}.aspx",
false,
new RouteValueDictionary(new {reportname = "Default"})
);
Not massively confident it will sort your problem but with it working with your original example it could well do.
Ok I had a huge Issue giving this a proper title, my excuses for that.
Anyways I have started slowly to look at Web and ASP.NET again, I am a C# developer but I have mostly worked with Windows applications the past 5 years or so, It is not that I haven't touched the web as such in that time, but this is as web services (Restfull as well as the ugly SOAP services) I have also worked with more "raw" web requests.
But I have not worked with IIS or ASP.NET in all that time.
What I would like to do is hos a web page that uses a URL style I could best describe with "like rest", hence the "Restfull urls" title. Because I think most people thinks of such URL's in terms of:
http://example.com/item/
http://example.com/item/23/
and so forth. Not that they have to look like that, however I would like to use such URL's instead of
http://example.com/item?id=23
I know subtext does this, but i have not had any luck finding it in their code base.
Now as far as I can tell I could just implement some IHttpHandler's, but at least for the examples I have seen of that, they write the page source back in code, and I still have master pages etc. I wish to use instead of taking over all that stuff my self, I really just kinda wants to route http://example.com/item/23/ to http://example.com/item and asking for the item with id 23...
I hope this makes sense at all >.<... And that someone has some better examples at hand that what I have been able to find.
You can achieve this using Routing here is a link to an MSDN blog, The .Net Endpoint - Using Routes to Compose WCF WebHttp Services that should get you started.
If you're looking at asp.net/IIS, another option to look at is ASP.Net MVC. It's pretty straight forward to create RESTful services.
Here's a tutorial:
http://www.codeproject.com/Articles/233572/Build-truly-RESTful-API-and-website-using-same-ASP
So here are your options-
For .net 3.5 sp1 framework with IIS7 you can use asp.net routing feature to have MVC style urls that you mentioned should create a custom route handler implementing IRouteHandler interface as explained here How to: Use Routing with Web Forms and register your route rules in Application_Start method in Global.asax. For your example you can register a route like this
routes.Add("ItemRoute", new Route
(
"item/{itemId}",
new CustomRouteHandler("~/item.aspx")
));
and then you can access itemId in your routed item.aspx page by checking request context item
requestContext.HttpContext.Items["itemId"]
For .net framework 4 MVC you dont have to create a custom handler, you can directly use
routes.MapPageRoute("ItemRoute", "item/{itemId}", "~/item.aspx");
in you global.asax Application_Start method.
This link explains more about the Routing
A way of achieve this is using URL rewriting.
If you're planning to host your Web application in Internet Information Services 7.x, you can take advantage of IIS URL Rewriting Module:
http://www.iis.net/download/urlrewrite
URL rewriting is just mapping a friendly URL to an unfriendly, common one, which is programming-friendly to inspect GET parameters.
For example:
http://yourdomain.com/item/48 => http://yourdomain.com/Items.aspx?Id=48