Как изменить корень статического файла ASP.NET MVC - PullRequest
9 голосов
/ 14 июня 2011

Я хочу иметь возможность реорганизовать структуру своего сайта ASP.NET MVC, чтобы она более точно соответствовала тому, как это делает Rails (у нас в компании есть и rails, и ASP.net).

В Rails есть «общедоступная» папка, которая ведет себя как корень сайта. Например, я мог бы зайти в «test.html» и получить доступ к файлу с помощью URL http://domain.com/test.html, который будет служить для статического html-файла.

В asp.net MVC есть папка «Content», которую я хочу вести как корень. Поэтому вместо доступа к http://domain.com/content/myfile.html, я хочу иметь возможность сделать http://domain.com/myfile.html.

Я знаю, что могу просто удалить файл в корне проекта, но мне нужно сделать это со многими файлами, включая css, js, html, изображения и т. Д., И хочу поделиться некоторыми стандартизированными активами через rails и aspnetmvc.

Есть ли способ сделать это?

Ответы [ 2 ]

8 голосов
/ 15 июня 2011

Существует еще одно возможное решение.Вместо использования кода вы можете использовать правило перезаписи, чтобы справиться с этим за вас.Если вы используете IIS 7 или выше, вы можете использовать модуль перезаписи URL-адресов Microsoft.

Правило, подобное следующему, вероятно, сделает это:

<rule name="Rewrite static files to content" stopProcessing="true">
  <match url="^([^/]+(?:\.css|\.js))$" />
  <conditions>
      <add input="{APPL_PHYSICAL_PATH}content{SCRIPT_NAME}" matchType="IsFile" />
  </conditions>
  <action type="Rewrite" url="/content/{R:1}" />
</rule>

Правило проверяет запрос кcss или js файл вне корня сайта.Затем он проверяет, существует ли файл в папке содержимого.Если он существует, то перезапись вернет файл в папку содержимого.Я только немного проверил это, но это похоже на работу.Это, безусловно, нуждается в дополнительном тестировании и возможной доработке.

2 голосов
/ 15 июня 2011

Единственное решение, которое я могу придумать, это использовать собственный контроллер и маршрут, чтобы сделать это для вас.Но это не чистое решение.

Сначала вам нужен класс PublicController с методом действия GetFile.Это предполагает, что все файлы находятся в папке public / content напрямую.Обработка папок усложняет задачу.

public class PublicController : Controller
{
    private IDictionary<String, String> mimeTypes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
                                                        {{"css", "text/css"}, {"jpg", "image/jpg"}};

    public ActionResult GetFile(string file)
    {
        var path = Path.Combine(Server.MapPath("~/Content"), file);

        if (!System.IO.File.Exists(path)) throw new HttpException(404, "File Not Found");
        var extension = GetExtension(file); // psuedocode
        var mimetype = mimeTypes.ContainsKey(extension) ? mimeTypes[extension] : "text/plain";
        return File(path, mimetype);
    }
}

Теперь вам нужен маршрут в нижней части списка маршрутов, который выглядит следующим образом:

routes.MapRoute("PublicContent", "{file}", new {controller = "Public", action = "GetFile"});

Проблема в том, что теперькогда вы просто вводите имя контроллера, например «Home», вместо значения по умолчанию для метода действия Index на HomeController, предполагается, что вы хотите загрузить файл с именем «Home» из каталога содержимого.Итак, над маршрутом к файлу вам нужно добавить маршрут для каждого контроллера, чтобы он знал, что вместо этого нужно получить действие Index.

routes.MapRoute("HomeIndex", "Home", new { controller = "Home", action = "Index" });

Итак, один из способов - изменить маршрут на следующий:

routes.MapRoute("PublicContent", "{file}.{extension}", new {controller = "Public", action = "GetFile"});

И метод действия для этого:

    public ActionResult GetFile(string file, string extension)
    {
        var path = Path.Combine(Server.MapPath("~/Content"), file + "." + extension);

        if (!System.IO.File.Exists(path)) throw new HttpException(404, "File Not Found");

        var mimetype = mimeTypes.ContainsKey(extension) ? mimeTypes[extension] : "text/plain";
        return File(path, mimetype);
    }

Как я уже сказал, это предполагает, что все файлы находятся в каталоге содержимого, а не в подпапках.Но если вы хотите создать подпапки, например Content / css / site.css, вы можете добавить свои маршруты следующим образом:

        routes.MapRoute("PublicContent_sub", "{subfolder}/{file}.{extension}", new { controller = "Public", action = "GetFileInFolder" });
        routes.MapRoute("PublicContent", "{file}.{extension}", new { controller = "Public", action = "GetFile"});

Теперь метод действия тоже должен измениться.

    public ActionResult GetFile(string file, string extension)
    {
        return GetFileInFolder("", file, extension);
    }

    public ActionResult GetFileInFolder(string subfolder, string file, string extension)
    {
        var path = Path.Combine(Server.MapPath("~/Content"), subfolder, file + "." + extension);

        if (!System.IO.File.Exists(path)) throw new HttpException(404, "File Not Found");

        var mimetype = mimeTypes.ContainsKey(extension) ? mimeTypes[extension] : "text/plain";
        return File(path, mimetype);
    }

Если вы начинаете получать несколько уровней глубоко в структуре папок, это становится все уродливее и уродливее.Но, возможно, это будет работать для вас.Я уверен, что вы надеялись установить флажок в свойствах проекта, но если он есть, я не знаю об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...