2013-05-10 2 views
12

Я реализовал вид двигатель многопользовательского подобное тому, что описано здесь:Обработки макет свойство с видом на заказ Бритвы двигателя

которые позволяют мне переопределить места поиска для просмотра как это:

MasterLocationFormats = new[] 
    { 
     "~/Views/%1/{1}/{0}.cshtml", 
     "~/Views/%1/Shared/{0}.cshtml", 
     "~/Views/Default/{1}/{0}.cshtml", 
     "~/Views/Default/Shared/{0}.cshtml", 
    }; 

В котором %1 заменяется правильную папку для активного арендатора. Это работает только прекрасное исключение одной проблемы. Когда я определяю путь Layout на мой взгляд, как это:

Layout = "~/Views/Default/Shared/_MyLyout.cshtml"; 

Это своего рода поражения цели с мульти-договор аренды, так как я должен жестко закодировать точное расположение страницы макета. Я хочу быть в состоянии сделать что-то вроде этого:

Layout = "~/Views/%1/Shared/_MyLyout.cshtml"; 

Если бы я хотел, чтобы жильцы имеют один макет страницы, как бы я идти о поддержке этого?

Я попытался пустячным с методами вида двигателя, что я отменяю:

  • CreatePartialView
  • CreateView
  • FileExists

Но ничто не кажется, чтобы указать себя в стороне возможности динамически определять страницы макета.

Update:

Вот что я работаю до сих пор. Я использовал ответ на этот вопрос https://stackoverflow.com/a/9288455/292578 слегка изменен, чтобы создать HTML-помощник:

public static string GetLayoutPageForTenant(this HtmlHelper html, string LayoutPageName) 
{ 
    var layoutLocationFormats = new[] 
    { 
     "~/Views/{2}/{1}/{0}.cshtml", 
     "~/Views/{2}/Shared/{0}.cshtml", 
     "~/Views/Default/{1}/{0}.cshtml", 
     "~/Views/Default/Shared/{0}.cshtml", 
    }; 

    var controller = html.ViewContext.Controller as MultiTenantController; 
    if(controller != null) 
    { 
     var tenantName = controller.GetTenantSchema(); 
     var controllerName = html.ViewContext.RouteData.Values["Controller"].ToString(); 

     foreach(var item in layoutLocationFormats) 
     { 
      var resolveLayoutUrl = string.Format(item, LayoutPageName, controllerName, tenantName); 
      var fullLayoutPath = HostingEnvironment.IsHosted ? HostingEnvironment.MapPath(resolveLayoutUrl) : System.IO.Path.GetFullPath(resolveLayoutUrl); 
      if(File.Exists(fullLayoutPath)) return resolveLayoutUrl; 
     } 
    } 

    throw new Exception("Page not found."); 
} 

, который похож на то, что предложил Saravanan. Тогда я могу установить макет, на мой взгляд с этим кодом:

Layout = Html.GetLayoutPageForTenant("_Home"); 

К сожалению, это дублирует работу, которая делает пользовательский вид двигателя, который, кажется, как неправильный путь.

ответ

3

Я хотел бы предложить следующую идею,

В _ViewStart.cshtml файле, где мы устанавливаем страницы макета, вы можете использовать что-то вроде этого, с идеей Арендатора на основе макета URL или имя папки заполняется контроллером путем извлечения из БД.

@{ 
    Layout = ViewBag.TenantLayoutPageUrl; 
} 

или

@{ 
    Layout = string.Format("~/Views/{0}/Shared/_MyLyout.cshtml",ViewBag.TenantId); 
} 

Если у вас есть некоторые статические представления Арендатора данных, как статический Identity класс, который будет отслеживать настройки вашего арендатора, мы можем использовать и свести к минимуму поездки туда и обратно к БД ,

Пожалуйста, поделитесь своей идеей о реализации этого так что это будет полезно для сообщества

+0

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

+0

@Sparafusile: В этом случае у нас может быть резервный идентификатор в ViewBag. Поэтому в Contoller мы проверим, есть ли у арендатора специальная страница макета, поэтому мы установим эту папку в сумке просмотра, иначе мы установим имя папки арендатора. 'ViewBag.TenantFolderName =" defaultPath "; if (арендатор имеет customFolder) { ViewBag.TenantFolderName = tenantFolderName; } ' ИМХО, это будет безотказно. – Saravanan

+0

Хотя я согласен, что это может сработать, это своего рода поражение цели пользовательского механизма просмотра для выполнения всей работы в контроллере. Я продолжу искать более элегантное решение. – Sparafusile

1

Try,

public class CustomWebViewPage : WebViewPage 
{ 
    public override void ExecutePageHierarchy() 
    { 
     if (Context.Items["__MainView"] == null) 
     { 
      this.Layout = String.Format("~/Views/Shared/{0}/_Layout.cshtml", ViewContext.Controller.GetType().Namespace); 
      Context.Items["__MainView"] = "Not Null"; 
     } 
     base.ExecutePageHierarchy(); 
    } 

    public override void Execute() 
    { 
    } 
} 

public class CustomWebViewPage<T> : WebViewPage<T> 
{ 
    public override void ExecutePageHierarchy() 
    { 
     if (Context.Items["__MainView"] == null) 
     { 
      this.Layout = String.Format("~/Views/Shared/{0}/_Layout.cshtml", ViewContext.Controller.GetType().Namespace); 
      Context.Items["__MainView"] = "Not Null"; 
     } 
     base.ExecutePageHierarchy(); 
    } 

    public override void Execute() 
    { 
    } 
} 

<system.web.webPages.razor> 
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> 
    <pages pageBaseType="Mv4App.CustomWebViewPage"> 
0

Вы можете добавить следующие _ViewStart.cshtml в арендаторе рассматривает папку (~/Views/%1/_ViewStart.cshtml). Каждый арендатор может управлять своими файлами макетов.

@{ 
    Layout = VirtualPathUtility.GetDirectory(PageContext.Page.VirtualPath) + "Shared/_Layout.cshtml"; 
} 
+0

Это интересная идея, но я хочу иметь возможность использовать собственный макет с представлениями по умолчанию и/или использовать макет по умолчанию с пользовательскими представлениями. Если я не понимаю ваш ответ, я не могу это сделать с вашим кодом. – Sparafusile

+0

@Sparafusile Вы можете сделать это, вы можете поместить '_ViewStart.cshtml' в любые папки, которые вам нужно настроить, вы можете поместить их даже в папку контроллера или в папку по умолчанию. По умолчанию папка контроллера поиска Razor Engine для начальной страницы ('_ViewStart.cshtml'), если она не может найти родительскую папку try и т. Д. До корня приложения. –

Смежные вопросы