I’ve only just started using ASP.NET MVC, and I have a somewhat trivial question: it seems that each controller has an attached folder-like path, so that my site becomes mydomain.net/Home/something. Is it possible to somehow get rid of the /Home part, so that the Home controller becomes ‘default’ for my web site and it’s possible to just use mydomain.net/something instead?
Sure, just define a route like so:
routes.MapRoute("{action}/{id}", new {controller="Home", action="Index", id=""});
The only problem is what about requests for your other controllers? For example, is
/Product/Foo
A request for HomeController.Product("Foo") or ProductController.Foo()?
You might need to use constraints to make the distinction clear.
I did a blog post on a simple way to handle this. I created a route constraint that selects a controller that you want to use for the root of your site. Here is the blog post if you're interested.
Related
In the previous version of ASP.NET MVC, URLs like the following were tolerated: https://www.trap.com//house.
Now, this generates a 404, which makes sense in a way. I like that by default ASP.NET Core MVC now is less tolerant of nonsense in general.
But I am left wondering how to go about the suggestion of implementing a middleware to address the issue. I found this example, but I don't want to redirect the user to the "right" or canonical URL - I want to tolerate the bad one.
In other words, I want the URL https://www.trap.com//house to be routed as though it were the URL https://www.trap.com/house. Or the URL https://www.trap.com///house/////4 to be routed as though it were the URL https://www.trap.com/house/4.
What is the best way to achieve this? URL rewriting? Special routes? Something else?
The best way of course is to fix the applications sending incorrect URLs. In light of that not likely happening, I would suggest adding some URL rewrite rules that handle these before the url is handed off to MVC.
I ended up using the rewrite middleware to accomplish this, although I will probably end up removing it...
var rewriteOptions = new RewriteOptions()
.AddRewrite("^///?(.*)$", "/$1", false)
.AddRewrite("^///?(.*)///?(.*)$", "/$1/$2", false); //etc, maybe you could make a regex that catches all these patterns
app.UseRewriter(rewriteOptions);
I'm building an API using WebAPI that will be accessed via AJAX calls. However, the API controller will need more than just one POST method. I understand I can specify {action} in my routing, but because I've seen that this is not recommended - am I using the right tool? So 2 questions:
Is Web API the best tool for this, or is there something else I should be using?
Why should I not use more than one POST method in a WebApiController? Is including {action} in my routing a good enough solution to this problem?
1. Is Web API the best tool for this, or is there something else I should be using?
I think WebAPI is a fine choice for you, regardless of whether you have one or many POST calls per controller.
2. Why should I not use more than one POST method in a WebApiController?
To remain RESTFul you'll want a controller per entity type. Without getting too deep into details, a POST against a specific type of entity should be the 'ADD entity' call, and why would you have more than one of those? Having said that, you don't have to be fully RESTFul... if your requirements suite a multi-POST model then go for it, you can always refactor later if necessary.
...Is including {action} in my routing a good enough solution to this problem?
Again, if your goal is to be RESTFul then this isn't a great practice. However, if you have needs that are best achieved using action routings then go for it. REST is not the only model.
So I have been using http://attributerouting.net/ and love it. However, I cannot seem to wrap my head around when I should use RouteArea, or RoutePrefix, or both.
For instance, my thought is that with an API controller, use RouteArea("api"), and then for a prefix maybe use the main function of the controller? Any clarification would be helpful, thank you!
RouteArea is meant for use with MVC controllers, which have a formal concept of areas. In web api, just use RoutePrefix.
Is it possible to get the QueryString value without using ? or & in the url?
I would like to have it like this:
http://www.colors.com/Red
string id = Request.QueryString["?"];
Instead of following:
http://www.colors.com/?ColorID=Red
string id = Request.QueryString["ColorID"];
No. a query string is defined by the appearance of a ?.
The example you give would redirect the user to a directory.
If you want to still be able to access the value of color-id through Querystring, then you should look at Rewriting. This can be due to legacy code that you can't change or other forms of interacting with 3rd party code. The benefit or Rewriting is that the code that ends up being executed doesn't know how the url looked like before it was rewritten and it can keep working as if there were a Querystring parameter named ColorID.
In its simplest form you need to call the Rewrite method of HttpContext, which will spin up a new request internally that executes code that matches that url without the user noticing anything. One caveat of this can be, that your legacy code doesn't know how to render correct links in menus and stuff, so you would keep having urls like ?ColorID=Red where it should have been just Red.
In IIS 7 and up, there is a built in filter where you can write your rules and patterns so you don't need to write your own code that matches incoming requests and calls HttpContext.Rewrite. Read more about it here on MSDN.
Now, Routing is a whole other thing. Its a Asp.net feature and doesn't work on top of existing legacy code but needs to be used with it. Meaning that the executing code needs to know that the request was routed to it. This of course has many benefits and of you're writing a new system then i would definitively recommend using Routing over Rewriting. There is a good article here about the differences and some SO questions also cover the topic:
IIS URL Rewriting vs URL Routing
Url Rewriting vs. Routing
It sounds like you may want to implement an MVC website.
Take a look at this MSDN documentation for more information.
I have an interesting situation where I need to quickly provide a feature to a customer prior to our normal build schedule and outside of our normal build repository. I need it to go live tonight, without a recompile.
Our site is deployed with everything compiled into a DLL, besides the Views. This means that at anytime I can edit the Views on the fly in the middle of the day. Is there a way I can add a new page that can be invoked via HTTP GET or POST so that I can do some things I would normally do in a Controller without actually making a new Action, etc? I know this is not a good methodology and it won't be the long term solution, I just need a plan... business is business after all.
Edit: I also cannot edit the Global.asax routing table, it is also compiled.
The first thing you'd have to do is pull out your Routes into XML files so you could add routes on the fly (all it'd do is recycle the App-Pool). I also recommend pulling the Routes out of the web.config into their own .config file, that's referenced in the web.config.
The second thing is you would have to mix Webforms with ASP.NET MVC if you wanted to do this.
It's important to note that using UrlParameter.Optional is problematic with XML based routing, at least I never got it to work.
I believe because of the way routing works in MVC it will try to find a valid path using the Routing system first. Failing that it should look for the aspx page using the normal method of just looking for the file. Keep in mind that aspx files (or razor files) that are just asp.net pages should not be in the Views folder, as MVC apps are configured to refuse serving up files in that directory. I'm assuming your're just talking about a single page or two? Anything more complex than that and I would look at trying to separate them more strongly as in the article mentioned above.
You could mix classic webforms with MVC.
I'm almost positive you could add a new Controller class to the App_Code folder and it would get picked up without a compile needed.
I guess it all depends if you have a convention based route that will hit it or not.