Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Project subdirectory as root for static files

New to ASP.NET MVC, I am creating a web application using the Visual Studio 2013 wizard. It creates several folders from where static files are served: Content, Scripts, etc.

Frameworks in other languages (e.g. TurboGears) have an explicit directory only for static content, removing the risk of serving the source code of a page instead of processing it which is a typical configuration mistake of PHP sites.

ASP.NET however is happy to deliver anything in the application's root directory, e.g. http://localhost:1740/Project_Readme.html as long as it has the right extension. Only the Views folder is protected with a Web.config.

How do I configure the application to use another directory than the project's root directory for static files. E.g. if the file favicon.ico is put into the subdirectory Content, it should be accessible as http://localhost:1740/favicon.ico, but nothing outside of the Content directory unless returned by a controller.

Nothing should ever be executed in this directory, that is, if *.cshtml files are put into this directory, the files' contents (the source code) should be delivered as text/plain.

Final application will run using mod_mono on Linux.

like image 686
Meinersbur Avatar asked Sep 04 '14 15:09

Meinersbur


2 Answers

Update:

Ben,

The proposed solution works only with Owin. To get it working in an MVC application you have to use asp.net MVC 6 (part of asp.net core or asp.net 5) only. But, with Web API you can use the older versions too. To setup the application please use the following steps:

  1. Create an empty project using visual studio templates(don't select Web API or MVC)

  2. Add the following Nuget packages to the project:

    Microsoft.AspNet.WebApi

    Microsoft.AspNet.WebApi.Owin

    Microsoft.Owin.Host.SystemWeb

    Microsoft.Owin.StaticFiles

  3. Add a Startup.cs file and decorate the namespace with the following

[assembly: OwinStartup(typeof(Startup))]

  1. Add the following code to the Stratup.cs class

    public void Configuration(IAppBuilder app)
    {
        var config = new HttpConfiguration();
        config.MapHttpAttributeRoutes();
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new {id = RouteParameter.Optional}
            );
        //Configure the file/ static file serving middleware
        var physicalFileSystem = new PhysicalFileSystem(@".\client");
        var fileServerOptions = new FileServerOptions
        {
            EnableDefaultFiles = true,
            RequestPath = PathString.Empty,
            FileSystem = physicalFileSystem
        };
    
        fileServerOptions.DefaultFilesOptions.DefaultFileNames = new[] {"index.html"};
        fileServerOptions.StaticFileOptions.ServeUnknownFileTypes = true;
        fileServerOptions.StaticFileOptions.FileSystem = physicalFileSystem;
        app.UseFileServer(fileServerOptions);
        app.UseWebApi(config);
    }
    
    1. This should do the magic. Now you can host the application in IIS. IIS will serve the static assets only from client folder. Add Server folder and add controllers.

The Microsoft.Owin.Host.SystemWeb is what facilitates the hosting of Owin application in IIS. The file serve options help IIS to serve static files only from client folder.

Please let me know if you have any questions.


Based on your question, the project structure that you want to achieve should be like the following.

Project Structure

Basically you will have two folders only, Client and Server. Static files are served from client folder only. Server folder is not accessible. If this is what you need then it can be achieved easily with Owin Self Host with Static File Serving middleware.

Self host works with out any dependency on IIS. But, if your planning to host this application on Linux, you could use Asp.NET CORE 1.0. Later if you decide to host the application on IIS inside windows that can be achieved easily by adding the Microsot.Owin.Host.SystemWeb nuget package.

There are great blog posts on this topic. This is the link for one of them. Here is the link for achieving the same in Asp.NET Core.

I hope this solves your issues and please let me know if you have any questions.

Thank you, Soma.

like image 54
Soma Yarlagadda Avatar answered Nov 09 '22 16:11

Soma Yarlagadda


The best solution I found is to ignore asp.net normal way and write a new way

        public override void Init()
        {
            BeginRequest -= OnBeginRequest;
            BeginRequest += OnBeginRequest;
        }


        protected void OnBeginRequest(object sender, EventArgs e)
        {
            if (Request.Url.AbsolutePath.StartsWith("/endPoint"))
            {
                Context.RemapHandler(endPoint);
            }
            else
            {
                Context.RemapHandler(staticHandler);
            }
        }

Let endPoint and staticHandler implement IHttpHandler it works but every static file moves through c# so there might be a solution with better performance

like image 40
ben or Avatar answered Nov 09 '22 15:11

ben or