Extension-less IIS wildcard mapping - umbraco

I want to configure a wildcard mapping for a specific path, and send the requests to a HttpHandler. My URLs look like this:
http://www.example.com/api/v1/conversation/forums/232?some=value
http://www.example.com/api/v1/conversation/posts/212
This configuration doesnt match the URLs above.
<location path="api/v1/conversation">
<system.webServer>
<handlers>
<add name="ApiProxy" verb="*" path="*" preCondition="integratedMode" type="DemoProject.ApiProxy, DemoProject" />
</handlers>
</system.webServer>
</location>
It works when I add an extension to my URLs:
http://www.example.com/api/v1/conversation/forums/232.axd?some=value
http://www.example.com/api/v1/conversation/posts/212.axd
How do I make this work extension-less?

It turned out, that this problem was related to my website was running Umbraco CMS. Umbraco CMS has an AppSetting called "umbracoReservedPaths", which asks Umbraco to ignore specific paths.
The value was set to:
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
After adding ~/api/, everything worked as expected:
<add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/api/" />

Related

Umbraco / Azure Blob Storage - Able to upload images & view in Umbraco, but getting 404 Errors on front-end

I recently began integrating UmbracoFileSystemProviders.Azure from https://github.com/JimBobSquarePants/UmbracoFileSystemProviders.Azure and am able to do the following on my local machine & a dev environment...
I can log into Umbraco (v7.3.1/a1.0.5780.28249), upload an image &
have it appear in the appropriate container on our Azure blob
storage
I can view images at their corresponding azure address (i.e. "https://azureaccount.blob.core.windows.net/media-stage/9999/file-name.png")
I can view images within Umbraco's backend (i.e. "http://localhost:99999/umbraco/backoffice/UmbracoApi/Images/GetBigThumbnail?originalImagePath=%2Fmedia%2F9999%2Ffile-name.png")
However, I get a 404 error when I try to view images on the front-end (i.e. "http://www.sitedomain.com/media/9999/file-name.png"). I think this is because the site is still trying to find the front-end image within the site rather than in Azure (based on the fact that creating/removing a matching directory & image at the appropriate relative location causes the image to load or yield a 404). This issue is consistent across multiple browsers & image uploads (whether I upload through Umbraco or through Microsoft Azure Storage Explorer). Does anyone have any ideas how I might be able to resolve it?
The following are all of the files/code snippets I'm using that I think might be relevant to the issue (with client-specific data swapped out in favor of generic data for security)...
Relevant section of Config/FileSystemProviders.config:
<Provider alias="media" type="Our.Umbraco.FileSystemProviders.Azure.AzureBlobFileSystem, Our.Umbraco.FileSystemProviders.Azure">
<Parameters>
<add key="alias" value="media"/>
</Parameters>
</Provider>
Relevant sections of Web.config:
<appSettings>
<!--other data here-->
<add key="AzureBlobFileSystem.ConnectionString:media" value="DefaultEndpointsProtocol=https;AccountName=azureaccount;AccountKey=aBcDeFgHiJkLmNoPqRsTuVwXyZ==;EndpointSuffix=core.windows.net" />
<add key="AzureBlobFileSystem.ContainerName:media" value="media-stage" />
<add key="AzureBlobFileSystem.RootUrl:media" value="https://azureaccount.blob.core.windows.net/" />
<add key="AzureBlobFileSystem.MaxDays:media" value="365" />
<add key="AzureBlobFileSystem.UseDefaultRoute:media" value="true" />
<add key="AzureBlobFileSystem.UsePrivateContainer:media" value="false" />
<!--other data here-->
</appSettings>
<location path="Media">
<system.webServer>
<handlers>
<remove name="StaticFileHandler" />
<add name="StaticFileHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.StaticFileHandler" />
</handlers>
</system.webServer>
</location>
A few additional notes for the troubleshooting process...
I've seen a few similar issues posted on GitHub (& closed out), but I believe my situation to be unique because...
I am not seeing configuration errors when I view the project or
umbraco backend (as with
https://github.com/JimBobSquarePants/UmbracoFileSystemProviders.Azure/issues/103)
My Umbraco is version 7.3.1 (rather than 7.5+, like https://github.com/JimBobSquarePants/UmbracoFileSystemProviders.Azure/issues/57)
Commenting out the image processor in the web config does not solve the issue (as with
https://github.com/JimBobSquarePants/UmbracoFileSystemProviders.Azure/issues/27)
I've also tried forgoing the web.config approach & using the following within Config/FileSystemProviders.config (again, client-specific data has been replaced with generalized stuff), but still had the same problem...
<Provider alias="media" type="Our.Umbraco.FileSystemProviders.Azure.AzureBlobFileSystem, Our.Umbraco.FileSystemProviders.Azure">
<Parameters>
<add key="containerName" value="media-stage" />
<add key="rootUrl" value="https://azureaccount.blob.core.windows.net/" />
<add key="connectionString" value="DefaultEndpointsProtocol=https;AccountName=azureaccount;AccountKey=aBcDeFgHiJkLmNoPqRsTuVwXyZ==;EndpointSuffix=core.windows.net"/>
<add key="maxDays" value="365" />
<add key="useDefaultRoute" value="true" />
<add key="usePrivateContainer" value="false" />
</Parameters>
Thanks in advance for any assistance!
I found that I needed to disable the Virtual Path Provider otherwise the URLs generated were always relative (of the form /media/nnnnn/filename.jpg). Hence I added this to web.config AppSettings
<add key="AzureBlobFileSystem.DisableVirtualPathProvider" value="true" />
see https://github.com/JimBobSquarePants/UmbracoFileSystemProviders.Azure.
This was with Umbraco version 7.7.7.

ASP.Net MVC: elmah.axd will be accessible for admin role only

i read this article to implement elmah http://www.c-sharpcorner.com/UploadFile/858292/exception-logging-in-mvc-using-elmah/
but i want only authorized person with admin role can see the elmah.axd file. how could i do it? guide me.
i found one way to attach elmah.axd file with admin role. here is code
https://blog.elmah.io/elmah-tutorial/
<location path="elmah.axd">
<system.web>
<httpHandlers>
<add verb="POST,GET,HEAD"
path="elmah.axd"
type="Elmah.ErrorLogPageFactory, Elmah" />
</httpHandlers>
<authorization>
<allow roles="admin" />
<deny users="*" />
</authorization>
</system.web>
<system.webServer>
<handlers>
<add name="ELMAH"
verb="POST,GET,HEAD"
path="elmah.axd"
type="Elmah.ErrorLogPageFactory, Elmah"
preCondition="integratedMode" />
</handlers>
</system.webServer>
</location>
tell me the above way is the only way to protect elmah.axd file for admin role.
from this link https://blog.elmah.io/elmah-security-and-allowremoteaccess-explained/
i found this one
<appSettings>
<add key="elmah.mvc.requiresAuthentication" value="true" />
<add key="elmah.mvc.allowedRoles" value="Admin" />
<add key="elmah.mvc.allowedUsers" value="Thomas" />
</appSettings>
if i add the above entry in web.config file then no authorized user other than admin role can not access elmah.axd file.......i have doubt. please some one guide me.
As I understand it from the docs, the first example is a general solution for ASP.NET. This has some issues with MVC, specifically with MVC's HandleErrorAttribute as well as getting custom errors.
The second example is for Elmah.MVC, a package specifically catering to ASP.NET MVC. This is the recommended way to set up Elmah when using the MVC framework.
<appSettings>
<add key="elmah.mvc.requiresAuthentication" value="true" />
<add key="elmah.mvc.allowedRoles" value="Admin" />
<add key="elmah.mvc.allowedUsers" value="Thomas" />
</appSettings>
What about ASP.NET MVC?
ELMAH were originally created for ASP.NET. Different features
available in ASP.NET MVC have been causing a lot of head-scratching
since introduced back in 2007. Some of you may have struggled with
MVC's HandleErrorAttribute as well as getting custom errors and ELMAH
working at the same time. In 2011, Alexander Beletsky created the
Elmah.MVC package to help MVC developers using ELMAH. We highly
recommend MVC projects to use this package, since it removes a lot of
the frustrations that people are having with MVC and ELMAH.
https://blog.elmah.io/elmah-security-and-allowremoteaccess-explained/

IIS hijacks CORS Preflight OPTIONS request

I am making a CORS POST request and setting the Content-Type header to json. This triggers a Preflight OPTIONS request to fire (this is good and expected)
This OPTIONS request is responded to with a 200 OK but this isn't coming from my WebAPI application.
I have a custom Message Handler in place and it never get's hit so the request is getting responded to by IIS prior to hitting ASP.NET it seems.
I have found several posts on the subject and they say the following
Make sure WebDav is uninstalled / removed / disabled - DONE
Make sure the OPTIONSVerbHandler is removed / changed to use aspnet_isapi.dll - TRIED BOTH
Make sure the extensionlessURLHandler includes the OPTIONS verb - DONE
However, my options request is still getting hijacked. By that I mean, IIS responds with at 200 OK but isn't including an Access-Control-Allow-Origin header in the response. It isn't including this header because it is never getting to my WebAPI CORS code that would set this header.
The two best posts I could find that sound like my issue are
here: JQuery stuck at CORS preflight and IIS ghost response
and here: http://brockallen.com/2012/10/18/cors-iis-and-webdav/
I have tried turning on Failed Request tracing (FERB) in IIS and set it to trace all 200 status codes. I don't ever see the options request being logged... Not sure if this means FERB doesn't track OPTIONS requests or if I need to change something in the FERB settings to make it track OPTIONS requests, Or if this is a clue to what my problem is?
This is ASP.NET WebAPI 2.0 running on IIS 7.5 (Also tested on IIS 8 and IISExpress with same results)
Doesn't matter what browser (Chrome, FF, and IE all fail the same way)
I have tried everything I can find on the subject and still can't fix my problem.
Help me StackOverflow, you're my only hope.
A couple of things you can try here, all web.config related, firstly modify your modules element to include the attribute runAllManagedModulesForAllRequests="true", as below:
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDavModule" />
</modules>
Then set your handlers to the below:
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="WebDav" />
<remove name="OPTIONSVerbHandler" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
This should do the trick, but if it doesn't, as a last resort you can force IIS to output the correct headers with the below:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
</system.webServer>
Be wary of the wildcard value, you should really set this to the domain name that your site will be hosted on.
that's what worked for me after 4 hours of searching/experimenting:
<handlers>
<remove name="OPTIONSVerbHandler" />
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="IsapiModule" scriptProcessor="C:\Windows\System32\inetsrv\asp.dll" resourceType="Unspecified" requireAccess="None" />
</handlers>
I tried all of the above suggestions as well as others I found on SO and what mattered in my situation was we had Request Filtering enabled on IIS and the OPTIONS HTTP Verb was not in the list of allowed verbs. Once I added it I was able to sort out the rest of it.
I had the same issue and the following web.config settings fixed it for me.
<modules runAllManagedModulesForAllRequests="false">
<remove name="FormsAuthenticationModule" />
</modules>
<handlers>
<remove name="OPTIONSVerbHandler" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
I was then able to handle CORS OPTIONS requests manually in Application_BeginRequest.
I was originally using the library detailed in this blog post for handling CORS requests. The product I'm working on requires that runAllManagedModulesForAllRequests be set to false, though. This is why I had to set up a custom implementation, but if you don't have that requirement you should give that library a try. It worked great when I was able to have runAllManagedModulesForAllRequests set to true.
In our case it was request filtering in IIS disabling OPTIONS verb at the root web application level. Open up IIS Manager, click on root application, click on Request Filtering, if OPTIONS appears in list either remove or Allow Verb. Wish I had checked this first as lots of wasted time.
In my case, I missed the Microsoft.WebApi.Cors package.
Installed this package and configured it like so in the WebApiConfig class:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.EnableCors(new EnableCorsAttribute("*","*","*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Please fine-tune this before using in production because you probably don't want to have wild-cards for everything
This is what worked for me:
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Check if URLScan tool is installed on IIS.
When so check following section:
;
; The verbs (aka HTTP methods) listed here are those commonly
; processed by a typical IIS server.
;
; Note that these entries are effective if "UseAllowVerbs=1"
; is set in the [Options] section above.
;
GET
HEAD
POST
OPTIONS
I know this is an old post, but I just went through the exact same problem.
In my situation, I have CORS installed for both OWIN and WebAPI. The OWIN CORS middleware was intercepting the OPTIONS call long before it ever made it to the WebAPI stuff. Maybe this well help someone else in the future.
I have installed Microsoft.AspNet.WebApi.Cors & Microsoft.Owin.Cors for my oWin based WebAPI and added app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); at config like below:
public class Startup : IStartup, IAppStartup
{
public void Configuration(IAppBuilder app)
{
var config = this.GetInjectionConfiguration();
BootstrapperWebApi bootstrapperWebApi = (BootstrapperWebApi)this.GetBootstrapperWebApi(config);
bootstrapperWebApi.Initialize(true)
.EnableLogging()
.DisableWebApiDefaultExceptionHandler();
WebApiConfig.Register(config);
app.UseOwinExceptionHandler();
app.Use<LoggerMiddleware>();
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
//others stuff
}
I tried all the mentioned posts but nothing worked for me, then i shifted my ASP.Net Web API 2 service to windows server 2012 (IIS 8.5) and same service worked without any changes. So issue was specific to IIS 7.5 on windows 7 machine.
In my case I did this:
<verbs allowUnlisted="true" applyToWebDAV="true">
<remove verb="OPTIONS"/>
<add verb="OPTIONS" allowed="true"/>
</verbs>
</requestFiltering>
</security>
When I added <add verb="OPTIONS" allowed="true"/> to the web.config, the application failed to start with this error
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Cannot add duplicate collection entry of type 'add' with unique key attribute 'verb' set to 'OPTIONS'
So I had to remove it first.
I have the same issue. The OPTIONS request return 200 OK status but it does not contain Access-Control-Allow-Origin header. The problem was our customer network policy blocking the OPTIONS verb request and response the warning message with 200 OK status. I know this is the old post but I want to share my case for anyone needed.
One more case, maybe it will save time for somebody. When I used config with HttpConfiguration.EnableCors all was working fine but when I used web.config file it was failing with CORS errors. It started work after I removed the .vs folder.
<figure>
<img src="https://i.stack.imgur.com/CbRyM.png" alt="">
<figcaption> change the OptionsVerbHangle</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/wjcMV.png" alt="Minha Figura">
<figcaption>Adicione * and in the case of php use fastcgimodule</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/wRwpi.png" alt="Minha Figura">
<figcaption>Mapping to folder
</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/hhqJi.png" alt="Minha Figura">
<figcaption>all verbs
</figcaption>
</figure>
<figure>
<img src="https://i.stack.imgur.com/86kKX.png" alt="Minha Figura">
<figcaption>Select script
</figcaption>
</figure>
Just follow the images below to unlock the colors in IIS
enter image description here
enter image description here
enter image description here
enter image description here
enter image description here
enter image description here

return View("myHtmlPage.html") in Asp.net MVC

Masters,
In my MVC application many pages are static (HTML pages).
I've to create both .cshtml and plain HTML pages.
HTML version is also in use by another module.
When I try with return View("Mypage.html") it fails.
Is there any way to consume plain "HTML" pages for my View.
Please help.
What I did in the past was to register ".html" pages to be interpreted as dynamic pages, too. (I.e. just like ASPX).
This can be done through your "web.config" file:
....
<
system.web>
<compilation ...>
<buildProviders>
<add extension=".html"
type="System.Web.Compilation.PageBuildProvider" />
</buildProviders>
....and
....
<system.webServer>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated" />
<add name="PageHandlerFactory-Integrated-HTML" path="*.html"
verb="GET,HEAD,POST,DEBUG" type="System.Web.UI.PageHandlerFactory"
resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
this works well with IIS 7 and IIS 7.5 (and probably on above versions, too). If you are using IIS 6, you have to do it through the IIS Management Console.
Hope this helps..

Is there any way to have a file extension in a bundle name?

I would like to have define a bundle like this:
bundles.Add(
new StyleBundle("~/style.css").Include(
//...
));
If the bundle name is just "~/style" this works, but with the file extension it always returns a 404. I suspect the server searches for CSS and JS files on the drive and ignores the bundling system, but I can't find anyone else who is trying to include file extensions in bundle names. Is this possible to do without something like a URL rewrite?
You could add the following to your <system.webServer> section in web.config:
<modules runAllManagedModulesForAllRequests="true" />
This will ensure that requests for static resources such as .js and .css will pass through the managed modules and be intercepted by ASP.NET MVC.
As an alternative to enabling runAllManagedModulesForAllRequests for all requests you could configure them only for the urls you need to use. So inside the <handlers> add the following:
<handlers>
<!-- ... -->
<add name="scriptBundle" verb="*" path="script.js" type="System.Web.Optimization.BundleHandler, System.Web.Optimization" preCondition="managedHandler" />
<add name="cssBundle" verb="*" path="style.css" type="System.Web.Optimization.BundleHandler, System.Web.Optimization" preCondition="managedHandler" />
</handlers>

Resources