Near the bottom of my routing registration, if a URL has a .js extension, I'd like to handle it with a particular controller (most .js content is served statically, but some is special and needs to be served via a controller). However, the following route is being skipped, and the catch-all route is handling the request.
routes.MapRoute("ContentScript", "{script}.js",
new { controller = "Content", action = "Script" },
new[] { "NameSpace.Controllers" }
);
What is the right way to do this?
In the route directly after that one every remaining request is routed like so (and this works and catches the .js files), so the issue is not in any part but the url parameter):
routes.MapRoute("ContentScript", "{*path}",
new { controller = "Content", action = "Index" },
new[] { "NameSpace.Controllers" }
);
I also tried the following, without success:
routes.MapRoute("ContentScript", "{*script}",
new { controller = "Content", action = "Script" },
new { script = new RegexConstraint("\\.js$") },
new[] { "NameSpace.Controllers" }
);
you have to add handler to the web.config so it can handle it ...
some thing like that :
<system.webserver>
<handlers>
<add name="scripts" path="*.js" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
</handlers>
</system.webserver>
stackoverflow link #1
stackoverflow link #2
The problem was an IgnoreRoute that I was unaware of (the RouteRegistry.cs file is 1,469 lines long... I have not studied it in its entirety, yet). js files are being handled in managed code--they were just being taken out by this before my route could handle the request.
routes.IgnoreRoute("{*path}",
new { path = new RegexConstraint(#"[^?]*\.(gif|jpe?g|png|ico|js|swf|css|txt|html?|xml|pdf)") }
);
Related
I have action:
public ActionResult Thumbnail(string image)
{
return GetThumbnail(image);
}
I am trying to access it with the next request:
http://localhost:60955/thumbnail/imagename.png
In config I have:
<add name="Png" path="/thumbnail/*.png" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
And in routes configuration:
routes.MapRoute(
name: "Thumbnail",
url: "thumbnail/{*image}",
defaults: new { controller = "Image", action = "Thumbnail" }
);
So it works for the above image URL. But I need this to work for any subfolder and the following returns 404:
http://localhost:60955/thumbnail/screenshots/imagename.png
And when I add slash it works again:
http://localhost:60955/thumbnail/screenshots/imagename.png/
Can I make it work with no trailing slash?
I feel like I need to customize the handler path in the config but cannot figure out how.
You should use query string for this case
URL change to this
http://localhost:60955/thumbnail?image=screenshots/imagename.png
I have run into an issue recently where we have been told to remove the hash symbols from our Backbone applications. This presents two problems: (a) the ASP.NET routes need to handle any remotely linked URL (currently this is no problem with the hash symbols) so that we're not hitting a 404 error and (b) the proper route needs to be preserved and passed on to the client side (Backbone) application. We're currently using ASP.NET MVC5 and Web API 2 for our backend.
The setup
For an example (and test project), I've created a test project with Backbone - a simple C# ASP.NET MVC5 Web Application. It is pretty simple (here is a copy of the index.cshtml file, please ignore what is commented out as they'll be explained next):
<script type="text/javascript">
$(document).ready(function(event) {
Backbone.history.start({
//pushState: true,
//root: "/Home/Index/"
});
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
//appRouter.navigate("/test/sometext", { trigger: true });
//appRouter.navigate("/help", { trigger: true });
});
</script>
<div class="jumbotron">
<h3>Backbone PushState Test</h3>
</div>
<div class="row"></div>
Now, without pushState enabled I have no issue remote linking to this route, ie http://localhost/Home/Index#test/sometext
The result of which is that the div with a class of .row is now "Hello, sometext".
The problem
Enabling pushState will allow us to replace that pesky # in the URL with a /, ie: http://localhost/Home/Index/test/sometext. We can use the Backbone method of router.navigate("url", true); (as well as other methods) to use adjust the URL manually. However, this does not solve the problem of remote linking. So, when trying to access http://localhost/Home/Index/test/sample you just end up with the typical 404.0 error served by IIS. so, I assume that it is handled in in the RouteConfig.cs file - inside, I add a "CatchAll" route:
routes.MapRoute(
name: "CatchAll",
url: "{*clientRoute}",
defaults: new { controller = "Home", action = "Index" }
);
I also uncomment out the pushState and root attributes in the Backbone.history.start(); method:
Backbone.history.start({
pushState: true,
root: "/Home/Index/"
});
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
//appRouter.navigate("/test/sometext", { trigger: true });
//appRouter.navigate("/help", { trigger: true });
This allows me to at least let get past the 404.0 page when linking to these routes - which is good. However, none of the routes actually "trigger" when I head to them. After attempting to debug them in Chrome, Firefox, and IE11 I notice that none of the events fire. However, if I manually navigate to them using appRouter.navigate("/help", { trigger: true }); the routes are caught and events fired.
I'm at a loss at this point as to where I should start troubleshooting next. I've placed my Javascript inside of the $(document).ready() event as well as the window.onload event also (as well as not inside of an event); none of these correct the issue. Can anyone offer advice on where to look next?
You simply have to move Backbone.history.start after the "new Route" line.
var Route = Backbone.Router.extend({
routes: {
"test/:id": function (event) {
$(".row").html("Hello, " + event);
},
"help": function () {
alert("help!");
}
}
});
var appRouter = new Route();
Backbone.history.start({
pushState: true,
root: "/Home/Index/"
});
Make sure you go to ".../Home/Index/help". If it doesn't work, try temporarily removing the root and go to ".../help" to see if the root is the problem.
If you still have troubles, set a js breakpoint in Backbone.History.loadUrl on the "return" line. It is called from the final line of History.start to execute the current browser url on page load. "this.matchRoot()" must pass then, "fragment" is matched against each "route" or regexp string in "this.handlers". You can see why or why not the browser url matches the route regexps.
To set to the js breakpoint, press F12 in the browser to open the dev console, press Ctrl-O or Ctrl-P to open a js file, then type the name of the backbone js file. Then search for "loadUrl:". You can also search for "Router =" to find the start of the router class definition (same as for "View =" and "Model =" to find the backbone view/model implementation code). I find it quite useful to look at the backbone code when I have a question like this. It is surprisingly readable and what better place to get answers?
If your js files happen to be minified/compressed, preferably turn this off. Alternately you can try the browser unminify option. In Chrome this is the "{}" button or "pretty print". Then the js code is not all on 1 line and you can set breakpoints. But the function and variable names may still be mangled.
I have solved my own problem using what feels to be "hackish", via the following. If anyone can submit a better response it would be appreciated!
My Solution:
I globally override the default Backbone.Router.intilaize method (it is empty) with the following:
$(document).ready(function (event) {
var _root = "/Home/Index/";
_.extend(Backbone.Router.prototype, {
initialize: function () {
/* check for route & navigate to it */
var pathName = window.location.pathname;
var route = pathName.split(_root)[1];
if (route != undefined && route != "") {
route = "/" + route;
this.navigate("", { trigger: false });
this.navigate(route, { trigger: true });
}
}
});
});
i have a WebForms application, and am trying to use the uploadify jquery library.
It works fine in IE8, but doesn't in FF7, FF10, or FF3. The break point i put in Upload.ashx is not hit.
I did quite the search and found that it has to does with cookies, something like ASPXAUTH. I tried adding it to 'scriptData', but no success.
Any ideas?
Page code:
<script type="text/javascript">
$(document).ready(function () {
alert($(".hidcook").val());
// <![CDATA[
var id = "55";
var theString = "asdf";
$('#fileInput').uploadify({
'uploader': 'uploadify/uploadify.swf',
'script': 'Upload.ashx',
'scriptData': { 'id': id, 'foo': theString },
'cancelImg': 'uploadify/cancel.png',
'auto': true,
'multi': true,
'fileDesc': 'All Files',
'queueSizeLimit': 90,
'buttonText': 'Importar Planilha',
'folder': '/uploads',
'onAllComplete': function (event, queueID, fileObj, response, data) {
}
});
});
// ]]></script>
Upload.ashx:
public class Upload : IHttpHandler, IRequiresSessionState{
public void ProcessRequest(HttpContext context)
{
try
{
HttpPostedFile file = context.Request.Files["Filedata"]; //breakpoint
int id = (Int32.Parse(context.Request["id"]));
string foo = context.Request["foo"];
file.SaveAs("C:\\" + id.ToString() + foo + file.FileName);
context.Response.Write("1");
}
catch (Exception ex)
{
context.Response.Write("0");
}
}
If your website content is not public, add to web.config authorization access to the Handler.
<location path="Upload.ashx">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
There are some differences in how browsers implement file upload through flash component.
IE uses the same session. FF opens a new connection, so the server sees an un-authenticaded user that is trying to access a protected page.
I had an issue using MVC where uploadify didn't post to the controller action.
It was due to an authentication issue. Flash for some reason creates it's own separate cookie to the browser, so if the user has already been authenticated with the browser (ASPXAUTH) cookie, and then the swf file makes a separate request using it's own flash cookie (which has not been authenticated.
Run fiddler to see whats happening, you may find that the server request that the uploadify is making is being redirected to the login.aspx page.
Although I don't know why this would work in just IE?
I have an app setup that runs on a server where the url is rewritten to the app. it goes servername.com/myapp
I routed the app as follows:
routes.MapRoute(
"Default", // Route name
"myapp/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
So that it will always begin with "myapp" otherwise the server will redirect the url. Now the content can't be found. I've tried putting the urls in manually but it doesn't work.
Here's what my view looks like:
<link href="#Url.Content("~/Content/themes/Site.css")" rel="stylesheet" type="text/css" />
Nothing strange about this so I don't see why it shouldn't work. Perhaps the server is rewriting the urls for content as well, so is there any way to set Url.Content() to map accordingly?
I recently had the same problem. Here is what I used to solve it, although someone may find a somewhat easier way.
On the development webserver, it used the server's root which resolved as "/" and it resolved to "/appname" on the deployment webserver. I could hardcode to link to one, but it obviously failed for the other. The answer is to create strings that find it programmatically.
#{
string rootpath = HttpContext.Current.Request.ApplicationPath;
if(rootpath != "/") { rootpath = rootpath + "/"; }// add closing slash if missing
string contentpath = rootpath + "Content/themes/Site.css";
}
<link href="#contentpath" rel="stylesheet" type="text/css" />
I put the rootpath code into a static function in a separate class since I used it on every page with links or images.
I am using routing in asp.net 4 webforms. I have a theme dll which contains all the images, css and js files required for look and feel. I have only 1 page which dynamically loads the control in the page. I use routing to distinguish the request. Following routes are defined:
routes.Ignore("{resource}.axd/{*pathInfo}");
routes.MapPageRoute("Default-All-Pages", "Pages/{*OtherParams}", "~/Default.aspx", false);
Handler for managing the embedded resources is already defined. When the application is executed it by virtue of code, redirects the request to default.aspx. it then goes ahead to load the css file and again routes the request to default.aspx.
I want it to route the css/jpg request to virtual path handler and not the page. What route should I define so that the request for files will not be handled by default.aspx page?
routes.Ignore("{*allaspx}", new { allaspx = #".*\.aspx(/.*)?" });
routes.Ignore("{*allcss}", new { allcss = #".*\.css(/.*)?" });
routes.Ignore("{*alljpg}", new { alljpg = #".*\.jpg(/.*)?" });
routes.Ignore("{*alljs}", new { alljs = #".*\.js(/.*)?" });
This solved my problem.
The same way you're ignoring HttpHandlers, you can add ignore rules for css and jpg files:
routes.Ignore("{resource}.css/{*pathInfo}");
routes.Ignore("{resource}.jpg/{*pathInfo}");
These will be excluded from the route table and will be handled by any registered handlers/modules/ISAPI filters.