Preprocess png images before sending response - asp.net

Assuming we have MVC application and image located at: /Images/image1.png
and we have action that matches this specific route
[Route("Content/{filename}")]
public ActionResult GetImage(string filename)
{
// Process image (add watermark etc..)
}
The goal is to process the png file before it is sent to the browser.
The problem arise when we try to access this action:
/Content/image1.png
it returns 404 because .png extension is handled as static content so it thinks I'm trying to load image from that location. On the other hand if we add a slash: /Content/image1.png/ after filename it does work fine
Question is how can we make the iis to ignore png and handle it as a route instead of static content
I tried this in web.config without luck:
<system.webServer>
<staticContent>
<remove fileExtension=".png" />
</staticContent>
</system.webServer>

Ok. Found the solution. You need to add
<handlers>
<add name="PngFileHandler" path="*.png" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
Found here

Related

ExtensionlessUrlHandler causes 404 Not Found with default document on IIS

I recently updated some ASP.NET Nuget packages and modified the index.html file of my web site. Now I get 404-Not Found error but ONLY for the root path, i.e. when the web site address is typed without subdirectory or file name.
If I explicitly append "/index.html" then the default document is displayed correctly.
I also noticed that the line below in my web.config file has an unexpected behavior: If I remove the line, then the root path can be displayed, but the Web API requests return 404-Not Found response. If I keep it, then Web API requests work but the default document causes 404-Not Found.
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
The complete "handlers" section of web.config is as follows:
<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>
I made no changes to the default document setting or physical path file permissions. How can I fix this?
I just discovered that the problem has nothing to do with my modification in index.html. The actual cause originated from the way MVC routing works: I had just added MVC components to my project, and newly-added MVC route config started digesting all extensionless paths. As per this explanation, I just added an exception for the root path (the empty string), and the problem was fixed:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapMvcAttributeRoutes();
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("");
...
}
}

Creating a folder with the same name as a controller results in 404 - Web API 2

If one creates a root level folder with the same name/route as a controller IIS seems to try and route to the folder and not consult the WebAPI 2 routing.
Example:
ProjectA
|- Controllers/
|-- ExamplesController.cs
|- Examples/
ExamplesController
[RoutePrefix("examples")]
public class ExamplesController : ApiController
{
[HttpGet]
[Route("")]
public async Task<IHttpActionResult> Get()
{
// code
}
}
The expectation is that hit the controller, however IIS seems to try and browse the folder instead.
Example: http://localhost:123/examples
Attempted Solutions:
I've tried to play around the IIS Handlers to see if I can remove all other handlers but that didn't help
Web.config
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<clear/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
The routing system checks the file system to see if a URL matches a file/folder on the disk. If it finds a match, the routing is ignored and the request bypassed any route entries so that the file will be served directly. This is there so that static files are served without going through MVC Routing
To change this behavior you can set the RouteExistingFiles property to true in your RouteConfig, however this may impact your static files, so do test them thoroughly
routes.RouteExistingFiles = true;

Multiple Web.Config files - from a code point-of-view

ASP.NET allows for Web.Config files at sub-levels within a site structure. However, I can't find any articles discussing how this looks from code.
In the Orchard CMS there are config files all over the shop. There's even a config file in a folder containing only .CSS files! I'm new to larger-scale ASP.NET apps so...
Can someone just tell me if I'm right in my assumptions.
The config file can affect server settings, and hence how a server processes a request to a resource further down a site structure.
From a code point of view, if the same line of code in the same class queries the config file during a request for http://level1.resource then it could read a different value to when the same code executes during a request for http://level1/level2.resource (if there is a web.config at level2)
Overall, the way it works is based on the current request path.
Right?
you can use the multiple web.config files in the sub-folders level. Each folder will contains its own web.config. Multiple Web.config files can't be used at same level.
Below is code for root folder web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<appSettings>
<add key="root" value="This is from root web.config"></add>
<add key="MySetting" value="This my settings is from root web.config"></add>
</appSettings>
</configuration>
and following is code for sub folder web.config.
<?xml version="1.0"?>
<configuration>
<system.web>
</system.web>
<appSettings>
<add key="sub" value="This is from sub web.config settings"></add>
<add key="MySetting" value="This my settings is from sub folder web.config"></add>
</appSettings>
</configuration>
In C# , you can access the settigns of different configuration files as below.
System.Web.Configuration.WebConfigurationManager.AppSettings.Get("Root");
System.Web.Configuration.WebConfigurationManager.AppSettings.Get("MySetting")
This is an old question, but I just asked myself the same one specifically in the Orchard CMS context as per the original post, and I've got an Orchard specific answer.
In the root of Orchard CMS, there's a web.config that want to prevent all users from requesting individual static files. For example, you don't want people to download placement.info or theme.txt from the Theme folders. This is a good "block everything, allow what you need" approach.
<handlers accessPolicy="Script">
<!-- Clear all handlers, prevents executing code file extensions or returning any file contents. -->
<clear />
<!-- Return 404 for all requests via a managed handler. The URL routing handler will substitute the MVC request handler when routes match. -->
<add name="NotFound" path="*" verb="*" type="System.Web.HttpNotFoundHandler" preCondition="integratedMode" requireAccess="Script" />
[...]
</handlers>
The thing is, in subfolders such as Scripts (containing static js files), Styles (containing only lots of static css files), or Content (contains static images for example), you of course want to allow the web browser to request an individual file. So in these subfolders, you have an extra web.config that looks like this:
<handlers accessPolicy="Script,Read">
<!-- For any request to a file exists on disk, return it via native http module. AccessPolicy="Script" above is to allow for a managed 404 page. -->
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
</handlers>
PS: I'm currently playing with Themes, and for some reason I've had to add <remove name="StaticFile"/> before each <add name="StaticFile"...> in all these child web.config.

ASP.NET MVC Url Route supporting (dot)

I hope that you can help me with the below problem.
I am using ASP.NET MVC 3 on IIS7 and would like my application to support username's with dots.
Example: http://localhost/john.lee
This is how my Global.asax looks like: (http://localhost/{username})
routes.MapRoute(
"UserList",
"{username}",
new { controller = "Home", action = "ListAll" }
);
The applications works when I access other pages such as http://localhost/john.lee/details etc.
But the main user page doesn't work, I would like the app to work like Facebook where http://www.facebook.com/john.lee is supported.
I used below code and it didn't work for me at all:
<httpRuntime relaxedUrlToFileSystemMapping="true" />
I was able to use below code and get the app to accept dots but I definitely wouldn't like to use below code for many different reason, please tell me there is a way to overcome this problem.
<modules runAllManagedModulesForAllRequests="false" />
Add a UrlRoutingHandler to the web.config. This requires your url to be a bit more specific however (f.e. /Users/john.lee).
This forces every url starting with /Users to be treated as a MVC url:
<system.webServer>
<handlers>
<add name="UrlRoutingHandler"
type="System.Web.Routing.UrlRoutingHandler,
System.Web, Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
path="/Users/*"
verb="GET"/>
</handlers>
</system.webServer>
Just add this section to Web.config, and all requests to the route/{*pathInfo} will be handled by the specified handler, even when there are dots in pathInfo. (taken from ServiceStack MVC Host Web.config example and this answer https://stackoverflow.com/a/12151501/801189)
This should work for both IIS 6 & 7. You could assign specific handlers to different paths after the 'route' by modifying path="*" in 'add' elements
<location path="route">
<system.web>
<httpHandlers>
<add path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
</location>
I was facing the same issue. So the best solution for me is:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"></modules>
<system.webServer>
For anyone getting an 'Cannot create abstract class' exception when using the UrlRoutingHandler approach, it's likely due to:
Using a restricted 'path' (e.g. path="/Files/*") in your web.config declaration, and
A folder/path with the same name exists in your project
I don't think the dot is the problem here. AFAIK the only char that should not be in the user name is a /
Without seeing the route that matches john.lee/details it's hard to say what's wrong, but I'm guessing that you have another route that matches the url, preventing the user details route from being matched correctly.
I recommend using a tool like Glimpse to figure out what route is being matched.

Can you use relative paths when registering handlers in web.config

I need to register a httphandler in a sub folder ("myTest") to my web application.
I know that a solution would be to add a webconfig to the myTest folder, but that is not an option in this case.
I would like to add the following to my web.config (focus on the path attribute)
<system.webServer>
<handlers>
<add name="myHandler" verb="*" path="myTest/myHandler.axd" preCondition="integratedMode" type="xxxxxx.xxxx, xxxxxx" />
</handlers>
</system.webServer>
IIS 7 doesn't complain about the relative path, but it doesn't work either
Another option would be to just place and .ashx file in the folder. Then you don't need to register anything in web.config.
The path attribute shouldn't point to the handler itself, but specify the paths affected by that handler. So in your case:
<add name="myHandler" verb="*" path="/myTest/*" preCondition="integratedMode" type="YourHandlerAssembly.YourHandler, YourHandlerAssembly" />
Should pass all files in the myTest subfolder to your HttpHandler.

Resources