7

Is it possible to run an MVC application from a virtual directory in IIS7? I have built an open source utility app in ASP.NET MVC3 and wondering if that was a mistake; it likely is if the site cannot be run from a virtual directory.

Take a simple default route of /home/index if running from a virtual directory named /app, will actually be /app/home index. Which kind of messes things up for routing.

I don't want a user to have to change routes and recompile the project to use the app in a virtual directory. Is there a way to change a configuration parameter to indicate what the root folder of what the application is?

Brettski
  • 19,351
  • 15
  • 74
  • 97

5 Answers5

23

Is it possible to run an MVC application from a virtual directory in IIS7?

Not only that it is possible but it is the preferred way.

Which kind of messes things up for routing.

Not if you use Html helpers when dealing with urls which will take care of this.

Here's a typical example of what you should never do:

<script type="text/javascript">
    $.ajax({
        url: '/home/index'
    });
</script>

and here's how this should be done:

<script type="text/javascript">
    $.ajax({
        url: '@Url.Action("index", "home")'
    });
</script>

Here's another typical example of something that you should never do:

<a href="/home/index">Foo</a>

and here's how this should be written:

@Html.ActionLink("Foo", "Index", "Home")

Here's another example of something that you should never do:

<form action="/home/index" method="opst">

</form>

and here's how this should be written:

@using (Html.BeginForm("Index", "Home"))
{

}

I think you get the point.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • just curious: why is it the _preferred_ way? – M4N Jun 15 '11 at 15:29
  • 1
    @M4N, because every ASP.NET application (no matter whether it is MVC or not) must reside in a virtual directory. If you deploy it at the site root, this site root still represents a virtual directory. – Darin Dimitrov Jun 15 '11 at 15:31
  • 1
    OK got it. But there is nothing against deploying at the site root. – M4N Jun 15 '11 at 15:32
  • @M4N, absolutely nothing against. – Darin Dimitrov Jun 15 '11 at 15:32
  • 1
    What do I call from within a class (not a controller class or view) to get the path to say, /home/index? – Brettski Jun 15 '11 at 15:34
  • @Brettski: Generally, you don't. As much as possible, keep knowledge of URI values in the views. – Craig Stuntz Jun 15 '11 at 15:38
  • @Brettski, as @Craig said, you never do this. A class should never need to calculate urls. That's the responsibility of controllers, helpers, views, ... So if your class needs an url, pass it to it, but never have it calculate it (and even worse, hardcode it). – Darin Dimitrov Jun 15 '11 at 15:43
  • That makes perfect sense, certainly cleaner to pass the value in. Thank you. – Brettski Jun 15 '11 at 15:45
  • There are those as well that would say "url: '@Url.Action("index", "home")'" is incorrect too - that you should use json to get the javascript data and pass those in to the ajax call and not intermingle the code types. I do not though and would agree 100% with how Darin has it here (although razor parsing sometimes gets messed up by the mixing of code in a script block and these issues can be ignored) – Adam Tuliper Jun 15 '11 at 16:21
  • 3
    Because as developers we should be using REAL tools, the same tools we'd be using on a dev, staging, or production server. Why would anyone want to use some stupid shit cassini...it causes issues which i don't need to go into details why...look it up. Why NOT use IIS should be the question. The Dev community is a bunch of lazy asses who don't want to learn how to do their job...part of that is learning IIS, so you can learn about how app pools work, page handlers, and so much more. Get in the ballgame, stop using shitty cassini. THAT'S WHY. – PositiveGuy Feb 10 '12 at 23:10
  • Wish MS would stop making these amateur toys. What am I talking about? Stuff that is supposed to help devs do code easier but really are trash: ASP.NET Membership, Cassini, Sharepoint, Data Sets, shit like that. Developers need to stop using this trash and yes do some real code and code cleaner more scalable solutions than using these trashy tools. Code your own damn membership provider, why not. NO it's not that hard. – PositiveGuy Feb 10 '12 at 23:12
  • Hi. I am trying to run an MVC 4 application from a virtual directory but keep getting a global.asax error. Can you please tell if you got this to work. Would someone mind checking this question: http://stackoverflow.com/questions/15961052/getting-a-global-asax-file-error-when-using-virtual-directories-for-an-mvc-appli – Julian Dormon Apr 12 '13 at 12:47
3

Yes, that works fine, and no, it doesn't mess up routing. However, the app you're running may be buggy and not support that configuration.

You don't need a "configuration parameter," because IIS and ASP.NET already handle this correctly.

You do, however, need to avoid hard-coded URIs in your views.

E.g., do this:

<img src="<%: Url.Content("~/Content/Images/Image.png") %>" />

...instead of:

<img src="/Content/Images/Image.png" />

...and similarly for links and style sheet references.

Craig Stuntz
  • 125,891
  • 12
  • 252
  • 273
  • How might one avoid hard-coded URIs (for background images, custom fonts, etc) in style sheets? MVC Helper functions are not available in CSS files... – user3163495 Apr 13 '18 at 21:41
3

as far as i know routes are all based on the application root, not the actual root, so think of them as beginning with ~/, not /

nathan gonzalez
  • 11,817
  • 4
  • 41
  • 57
2

Yes this works. And as long as you're using the helper methods to create action URLs (e.g. <%=Html.ActionLink(...) %> there is no need to reconfigure or recompile.

M4N
  • 94,805
  • 45
  • 217
  • 260
  • So as long as I am using the helper methods in my views, ASP.NET MVC will just know where it is running from and base its urls and routing from that? – Brettski Jun 15 '11 at 15:33
  • @Brettski: exactly (see also Darin's detailed answer). – M4N Jun 15 '11 at 15:33
0

Just in case it helps someone, I ran into an issue where my MVC actions are dynamic so I could not have .net generate the correct url's for me using the methods described in the accepted answer's post. I could use "~/" server side but not in javascript, etc. My solution was to write a shared method that builds the url using the application's name that I get from:

System.Web.HttpRuntime.AppDomainAppVirtualPath

Example: "/maint/Manage/Users" where "maint" is the name of my application that may be different on some servers, "Manage" is the name of my controller and "Users" is a dynamic action that comes out of a database:

return string.Format("{0}/Manage/{1}", HttpRuntime.AppDomainAppVirtualPath, MenuName);
Bolo
  • 1,494
  • 1
  • 19
  • 19