Is any special routing or IIS config needed when a controller action uses the same URL as a virtual directory?
I have an ASP.NET MVC 1.0 application that needs Windows Authentication applied to a single action ("/Login/FromWindows"). To do this, we've setup a virtual directory with the same path as the action (e.g. "/Login/FromWindows") and enabled Windows Authentication on it in IIS.
When I visit the /Login/FromWindows URL, I get an empty HTTP 200 response and nothing is logged in the server text log. The "FromWindows" action should be logging messages and redirect the user to the home page.
It seems like the action code is simply not being executed, so there is possibly a conflict with the virtual directory.
Route config in Global.asax.cs
public static void RegisterRoutes(RouteCollection routes)
{
// snipped: ignored routes for images, scripts, etc.
routes.MapRoute( "Default", "{controller}/{action}",
new { controller = "Home", action = "Index" } );
}
You are right, the action code isn't being executed. That's because existing file paths (virtual or not) take precedence over MVC routing rules.
Why are you using a virtual directory? Just set authentication to windows in the web.config and use the [authorize] attribute over the corresponding action methods.
Web.config:
<configuration>
<system.web>
<authentication mode=”Windows” />
</system.web>
</configuration>
Action Method:
[Authorize]
public ActionResult SomeAction()
{
return View();
}
Visit http://www.asp.net/mvc/tutorials/authenticating-users-with-windows-authentication-vb for more information on mvc with windows authentication.
Just simple is using [Authorize] attribute a Chevex mention above, or if you want more, you can customize the Authorize by extension it for your business. IMHO.
Related
I have a url like www.abc.com in mvc3 application, i set a default map.route like this
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "UserLogOnPage", action = "LogOn", id = UrlParameter.Optional } // Parameter defaults
);
now what is happening when i type www.abc.com and enter it goes to Controller:UserLogOnPage Method:Logon and in browser url is also showing www.abc.com which is correct, but when enter url like www.abc.com/UserLogOnPage/Logon same method and controller ,i want url like www.abc.com not www.abc.com/UserLogOnPage/Logon how can i do this.
Thanks
I am almost certain this isn't what you are actually trying to do - that route configuration will result in any URL being redirected to the LogOn page.
Going by the url what it looks you are after is actually authentication i.e. if an anonymous user visits www.abc.com they are asked to log on before they can get access to the site.
Luckily for you, MVC has already done the hardwork all you need to do is decide how you want it to work. Authentication can be applied at various levels and the scope is determined by where via the AuthorizeAttribute is set.
Global.asax - authentication required by every action
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
...
filters.Add(new AuthorizeAttribute());
}
Controller - authentication required for all actions within a particular controller
[Authorize]
public class AccountController : Controller
{
...
}
Action - authentication required for this action only
[Authorize]
public ActionResult AccountDetails()
{
...
}
To determine which page you want users to be redirected to as a result of the AuthorizeAttribute, you can configure the authorization section in the web.config
<authentication mode="Forms">
<forms loginUrl="~/UserLogOnPage/LogOn" />
</authentication>
I'm getting a 302 error returning on a single CSS file on an ASP.NET MVC 2 site in localhost this morning and I don't know what would have changed to cause this.
The localhost site uses IIS 7.5, though I've had limited experience with IIS so I haven't looked to much in to what could be going on there.
The URL to the CSS file is:
http://localhost/MySite/Content/Site.css?v=16
and the location header on the response looks like this:
/MySite/Account/Login?ReturnUrl=%MySite%2fContent%2fSite.css%3fv%3d16&v=16
This makes me think that MVC is redirecting the static file or something like that, however if that was the case, then I would expect all my images, CSS and JavaScript files to be doing the same which they're not. Just in case, here is a simplified version of RegisterRoutes() in Global.ascx:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("", "Account/{action}/", new { controller = "Account" });
routes.MapRoute("", "{action}", new { controller = "Home", action = "Index" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Error",
"{*url}",
new { controller = "Home", action = "ResourceNotFound" }
);
}
Also, if I change the name of my CSS file to Site2.css and reference that instead, the same thing happens.
What's going on?
The redirect to the logon method makes it look like this is because of permissions on the directory or the file rather than an MVC route catching it. (If it were caught by an MVC route, it would probably rather result in an error determining which controller and/or action to use.)
ASP.NET MVC itself leaves static files alone, but if ASP.NET in general decides that the anonymous user doesn't have access to the CSS file or its directory, ASP.NET will redirect to the log-on URL, which will be an ASP.NET MVC action.
Looks like the authorization rules in the web.config are saying that you have to be authenticated to see the css pages. You should be able to prove that by logging in and seeing if you can get the css file to be served correctly.
I'd add a location section to the web.config to remove the authorization requirement on the content directory. Taken from http://support.microsoft.com/kb/316871
<!-- This section gives the unauthenticated user access to all of the files that are stored in the Content folder. -->
<location path="content">
<system.web>
<authorization>
<allow users ="*" />
</authorization>
</system.web>
</location>
I have an ASP.NET MVC application where the default page should be index.html which is an actual file on disk.
I can browse to the file using www.mydomain.com/index.html so I know it will be served and exists but if I use www.mydomain.com I get a 404.
I have ensured that the default document is correctly set in IIS7 and I have even gone so far as to commented out all the routes defined in my global.asax to ensure I don't have a route causing this problem.
So to summarize:
I have an index.html file on disk and IIS7 is set to use index.html as the default document.
If I remove my ASP.NET MVC application and leave the index.html file is served as the default document as expected.
If I publish my ASP.NET MVC application then the index.html doesn't get served by default document.
Does anyone know how to get ASP.NET MVC to serve the default document?
ASP.Net MVC routing is controlled by the Global.asax / Global.asax.cs files. The out-of-the-box routing looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
When no path is specified, ie. www.domain.tld/, the route is the empty string, "". Therefore the routing looks for a controller with that name. In other words, it looks for a controller with no name at all. When it finds no such controller it serves up a 404 NOT FOUND error page.
To solve the problem, either map that path to something meaningful or else ignore that route entirely, passing control over to the index.html file:
routes.IgnoreRoute("");
I had a similar problem with a WebForms application. In your web.config make sure the resourceType attribute of the StaticFile handler under system.webServer is set to Either.
<add name="StaticFile" path="*" verb="*" type="" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" scriptProcessor="" resourceType="Either" ...
I found a way around this. If you want index.html to be in the root of your MVC application (i.e next to your controller/model/view/appdata etc folders), you can do this:
Say you have home.html, aboutus.html and contactus.html.
//this route matches (http://mydomain.com/somekindofstring)
routes.MapRoute(
"SingleRootArg",
"{id}",
new { controller = "Home", action = "Details", id=""});
// so now that you have your route for all those random strings.
// I had to do this for vanity urls. mydomain.com/ronburgandy etc. however,
// mydomain.com/index.html will also come in just how you'd expect.
//Just an example of what you COULD do. the user would see it as root html.
Public ActionResult Details(string id)
{
//let me save you the trouble - favicon really comes in as a string *ANGER*
if(String.IsNullOrEmpty(id) || id.ToLower().Contains("favicon.ico"))
return Redirect("~/index.html");
if(id == "aboutus.html")
return Redirect("~/aboutus.html");
if(id == "contactus.html")
return Redirect("~/contactus.html");
if(id == "index.html")
return Redirect("~/index.html");
}
index.html aboutus.html index.html are now at the same level as my CSPROJ file.
Sorry for resurrecting this mummy, but i don't believe this issue was ever a default document issue. In fact you probably don't want to have a default document set as many of the other answerers have stated.
Had this problem as well, a similar problem. the cause of my issue was that the Application Pool for the site was set to use .NET Framework v2 and should have been set to v4. once I changed that it loaded correctly.
You could ignore the route in your MVC application and let IIS serve it.
routes.IgnoreRoute("index.html")
etc
I suspect you added index.html yourself as that extension would be unknown to the mvc framework.
Your default index page in mvc is //domain/home/index and is physically index.aspx.
If you call your domain using //domain then the routing engine will assume /home/index.aspx and not index.html.
i created a new solution and it builds fine targeting framework 4.0 but when i run it, my browser comes up saying:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /
any ideas on how to debug this?
Try adding the default.aspx page that comes with the asp.net mvc 1.0 project template. I had a similar issue running mvc 2 out of the box on a computer with IIS 5 (XP), and that did the trick.
Default.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="YourNamespace.Website.Default" %>
<%-- Please do not delete this file. It is used to ensure that ASP.NET MVC is activated by IIS when a user makes a "/" request to the server. --%>
Default.aspx.cs:
using System.Web;
using System.Web.Mvc;
using System.Web.UI;
namespace YourNamespace.Website
{
public partial class Default : Page
{
public void Page_Load(object sender, System.EventArgs e)
{
// Change the current path so that the Routing handler can correctly interpret
// the request, then restore the original path so that the OutputCache module
// can correctly process the response (if caching is enabled).
string originalPath = Request.Path;
HttpContext.Current.RewritePath(Request.ApplicationPath, false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(HttpContext.Current);
HttpContext.Current.RewritePath(originalPath, false);
}
}
}
You don't need to add the default.aspx page described above.
The browser will display this 404 message if you add and run a new Empty ASP.NET MVC 2 application "out of the box".
This is because of the default route that is defined in global.asax.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
You can see it is looking for a controller called Home and an action called Index.
When creating a new empty project it's left to you to create the Home controller and Index action (they are not there in an empty project), then create the view for the Index action too.
My guess is that you need to reregister or enable the framework under IIS.
Try running aspnet_regiis from the appropriate framework tree and / or make sure that the proper framework version is allowed under IIS web extensions.
I have deployed my application to a server running IIS6 using the method which invloves changing the routes to:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}.mvc/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
routes.MapRoute(
"Root",
"",
new { controller = "Home", action = "Index", id = "" }
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
And adding a handler in IIS for .mvc extentions. This is working fine for the most part until I add the [Authorize] attribute to HomeController class.
This ends up in the app trying to redirect the user to the logon page which is what I expect however the logon page URL is shown as http://server/virtualdir/Account/LogOn?ReturnUrl=%2fvirtualdir%2fDefault.aspx
This is causing a problem as no .mvc extension is being added to the Account controller part of the URL.
The problem has been solved by changing the following in web.config:
<authentication mode="Forms">
<forms loginUrl="~/Account.mvc/LogOn" timeout="2880" />
</authentication>
Not directly an answer to your question, but from my experience it worked just fine to deploy an application with the new routing features just as it is to IIS6 and add a wildcard mapping to aspnet_isapi.dll. Then you can use any URL you want, and nobody will notice when you change to a newer version in the future.
Yes, static file handling is theoretically less efficient this way, but you will need really a lot of traffic to notice anything. And if you really get a lot of traffic, you still could and even should move all your static files to a another domain/subdomain (or even a CDN) anyway, like stackoverflow.com does. It can still point to the same server, you just use different IIS settings for this subdomain site. But with e. g. just a few thousand visitors per day you don't even have to think about it.