MVC Route to Action for Javascript file - asp.net-mvc

I am trying to add a mvc route to generate a javascript from the controller. I have added the following route and it doesn't work:
routes.MapRouteWithName(
"DataSourceJS", // Route name
"Scripts/Entities/{controller}/datasource.js", // URL with parameters
new { controller = "Home", action = "DataSourceJS"} // Parameter defaults,
, null
);
But if I change the route to not have the ".js" and I navigate to "Scripts/Entities/{controller}/datasource" it works. But I need to have the .js file extension on there, how do I make this work?

how do I make this work?
IIS intercepts the request because it contains a file extension and hijacks it thinking it is a static file and not passing it to your application.
To make it work you should tell IIS not to do that. Inside the <system.webServer> section you could add the following handler to indicate that requests with the specified pattern should be handled by the managed pipeline:
<system.webServer>
<handlers>
...
<add name="ScriptsHandler" path="Scripts/Entities/*/datasource.js" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Some people might also tell you to use:
<modules runAllManagedModulesForAllRequests="true" />
but I wouldn't recommend you doing that because this means that all requests to static resources will now be flowing through the managed pipeline which could have a negative performance overhead for your application. The handler syntax allows you to selectively enable this only for certain route patterns and HTTP verbs.

Related

routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); [duplicate]

What is routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
I cannot find any .axd file in my project, can I remove this route rule?
.axd files don't exist physically. ASP.NET uses URLs with .axd extensions (ScriptResource.axd and WebResource.axd) internally, and they are handled by an HttpHandler.
Therefore, you should keep this rule, to prevent ASP.NET MVC from trying to handle the request instead of letting the dedicated HttpHandler do it.
Some Background
If you open up this file:
%WINDIR%\Microsoft.NET\Framework\version\Config\Web.config
you will find this within the file:
<add path="WebResource.axd"
verb="GET"
type="System.Web.Handlers.AssemblyResourceLoader"
validate="True" />
That is basically telling the Asp.NET runtime: "Hey asp.net dude, if a request comes for WebResource.axd then use AssemblyResourceLoader to process the request."
Please do note that WebResource.axd is NOT a file but simply a map (if I may say) to AssemblyResourceLoader. It is the name under which the handler is registered. On my machine, I found the following .axd handlers:
<add path="eurl.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True" />
<add path="trace.axd" verb="*" type="System.Web.Handlers.TraceHandler" validate="True" />
<add path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" validate="True" />
<add verb="*" path="*_AppService.axd"
Ok, so what does that handler do?
The AssemblyResourceLoader knows how to look for embedded files within an assembly so it can serve it (send it to the client i.e. a browser). For example, in asp.net web forms, if you use the validation controls, they depend on some javascript to show the errors on the web page. However, that javascript is embedded in an assembly. The browser needs the javascript so you will see this in the html of the page:
<script src="/YourSite/WebResource.axd?d=fs7zUa...&t=6342..." type="text/javascript"></script>
The AssemblyResourceLoader will find the assembly where the javascript is embedded using the information in the querystring and return the javascript.
Back to the Question
So to answer the question, what is:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
That is telling the routing engine that we will not be processing those requests that match that route pattern. In other words, we will not process .axd requests. Why? Because MVC itself is an HttpHandler similar to .axd and .aspx and many other handlers that are in the web.config file. The MVC handler does not know how to process the request such as looking for embedded resources in an assembly-the AssemblyResourceLoader knows how to do that. MVC knows how to do, well everything it does which is beyond the scope of this question and answer.
The route with the pattern {resource}.axd/{*pathInfo} is included to prevent requests for the Web resource files such as WebResource.axd or ScriptResource.axd from being passed to a controller.
Read link:
http://msdn.microsoft.com/en-us/library/cc668201%28v=vs.100%29.aspx
You can also specify that routing should not handle certain URL requests. You prevent routing from handling certain requests by defining a route and specifying that the StopRoutingHandler class should be used to handle that pattern. When a request is handled by a StopRoutingHandler object, the StopRoutingHandler object blocks any additional processing of the request as a route. Instead, the request is processed as an ASP.NET page, Web service, or other ASP.NET endpoint. You can use the RouteCollection.Ignore method (or RouteCollectionExtensions.IgnoreRoute for MVC applications) to create routes that use the StopRoutingHandler class.
Take a look in the below link:
http://haacked.com/archive/2008/07/14/make-routing-ignore-requests-for-a-file-extension.aspx
Those are not files (they don't exist on disk) - they are just names under which some HTTP handlers are registered.

Swap between MVC routing and Durandal routing

Long story short: We're trying to set up Durandal SPA in our pre-existing ASP.NET MVC website. What's we're going for is the ability to hide the SPA behind a feature flag, to where we can enable the SPA flag and have our website adjust accordingly.
We have that portion of it working. However, what we had to do is prefix all of our routes with "/app#" and then tack on the controller/action. For example, "Index" would become "app#Index" in the URL. Durandal routing works just fine with this approach - it pulls the necessary views into place.
What we would like is to use the same routes instead of prefixing each one with "app#" - essentially use Durandal routing when the SPA flag is enabled, otherwise use normal MVC routing, but keep the routes the same.
Any suggestions?
If you know about modules requires convention of the Durandal, will be very simple to understand, you just need to insert this configuration in the Web.config:
Web.config
<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" />
<add name="HtmlFileToMvcHandler" path="App/views/*/*.html" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
Observe that i created the handler "HtmlFileToMvcHandler" with this pattern "App/views/*/*.html" i used that pattern because my CRUD convention, and with this i told to the MVC handler that all of the requests that comes with this pattern will be handled. But now you need handle the requests that will came. So you can use the RouteAttribute like this:
[Route("App/View/Home/index.html")]
public ActionResult Index()
{
return View();
}
or map that route in the route config like this:
routes.MapRoute("Name",
"App/views/{controller}/{action}.html");
My english will be better in the next time XD

ASP.Net MVC4 Routing not working - reserved word?

In short, I have an MVC web app that has a proxy class to marshall requests to another web app under the context of the logged in user.
This all works fine except that some of the outgoing links (i.e. inbound links to my MVC app) from the other web app contain the url "/views".
These requests should be mapped according to this route:
routes.MapRoute(
name: "TableauViews",
url: "views",
defaults: new { controller = "Tableau", action = "Views" }
);
But it never happens. If I change the name of the controller action to something else and enter the corresponding url in a browser, it works.
This leads me to suspect that there is some problem mapping a url containing the word "views" as part of its path. Can anyone confirm this?
The issue is the order of operations. Views is a physical folder and a route. The ASP.NET HttpHandler will read the web.config and block anything going to views before the route handler picks up the URL. If you look at the web.config file in your views folder (where your views are actually stored) you will likely see something like this:
<httpHandlers>
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
Also, later in the config there may also be this:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
This is your culprit. I would suggest either naming your route something more like "externalViews" or simply "external" might help. The other alternative is to remove the line above from your views web.config, but this could result in some undesirable behavior.
This article deals with restricting only certain types of files from being delivered instead of blocking all that may be helpful for you.
http://blog.falafel.com/Blogs/j-tower/2014/03/28/loading-javascript-files-from-the-views-folder-in-asp-net-mvc
I couldn't find anything specifically saying "views" is a reserved word, but the article http://haacked.com/archive/2010/04/29/allowing-reserved-filenames-in-URLs.aspx describes how to relax the rules on what words can be used.

How to pass email as a parameter at the end of URL in ASP.NET MVC web API?

How to pass email as a parameter at the end of URL in ASP.NET MVC web API?
like below:
test.com/api/sales/getcustomerorders/test#test.com
I want to pass the email address as a parameter to the getcustomerorders action.
we can pass using query string. But I want to format the url like above.
Thanks.
In WebApiConfig make the route as "/{email}/". The end "/" will prevent you from getting No HTTP resource was found that matches the request URI ...
The problem here is that you have period in the url.
In order to make it work, change you web config to add following two configurations:
<configuration>
<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Haacked has a blog about relexUrlToFileSystemMapping http://haacked.com/archive/2010/04/29/allowing-reserved-filenames-in-URLs.aspx
And I have a bug about it in IIS express 8 and need the runAllManagedModulesForAllRequests:
https://aspnetwebstack.codeplex.com/workitem/226
Scott Hanselman covers this in this blog post. As an alternative you could pass the email as a query string parameter and not as part of the path since certain characters are not allowed.

Invoke ASP.NET MVC Controller When Requesting .html file

I need to add some new life to a legacy application :)
I'd like to call an MVC controller when a "static" HTML page is requested in order to add some markup to the page before returning it to the client.
I tried to follow the approach found in this thread: How to read web.config settings in .html page?
...but even though I have this route defined:
routes.MapRoute(
name: "Topic",
url: "html/{fileName}.html",
defaults: new { controller = "Topic", action = "Index" });
the controller is not being called. I have my web.config defined with:
<remove name="WebServiceHandlerFactory-Integrated" />
<add name="HTML" path="*.html" verb="*"
type="System.Web.UI.PageHandlerFactory"
resourceType="File" preCondition="integratedMode" />
I suspect that I need to call something else besides the PageHandlerFactory or perhaps the issue is something entirely different.
UPDATE: My dev environment is working with integrated pipeline mode, but I need to check if my production environment will support it.
If you do this:
routes.RouteExistingFiles = true;
You should find this works - even without the handler addition. In the controller you can load the HTML directly using the HostingEnvironment.VirtualPathProvider's GetFile method and do something with it - or better still just use a normal MVC view that renders the same content as the static file, just with your additions.
Although be aware that this means any files that are potentially caught by any routes will be pushed into the MVC pipeline. This isn't generally a concern, however, if decent separation of routes and physical paths is used.
I setup the same situation as you and it worked well for me, so you have the key components in place. Some things to keep in mind for the testing and troubleshooting:
Your web.config does need the build provider for the html extension:
<system.web>
<compilation>
<buildProviders>
<add extension=".html"
type="System.Web.Compilation.PageBuildProvider" />
</buildProviders>
</compilation>
</system.web>
A copy and paste of your handlers works for me, so that looks good.
And a copy and paste of your MapRoute works for me too, although I used the default Home controller in a clean project. So as a double check just confirm that you have a controller called Topic with an ActionResult method called Index().
And make sure that your url is localhost.com:{port}/html/test.html with the /html/ in the path since your rule asks for that.
Another good test is to change your MapRoute to use aspx instead and test an aspx page and see if that works. That will confirm whether or not it's the IIS mappings or if it's the MVC rules. If it works with aspx then the issue is related to the handler, but if it fails with aspx too then it's something with MVC.
Also confirm that you're using IIS Express and not Cassini. Cassini will not handle that correctly, but IIS Express will. You can confirm by right-clicking on your project and you should see a menu option called "Use Visual Studio Development Studio...". That will only exist if you are currently using IIS Express.

Resources