2013-05-10 11 views
12

I wprowadziły multi-tenant widok mechanizmu podobnego do tego, co jest opisane tutaj:właściwości Układ obchodzenia się z widokiem na zlecenie Razor silnika

które pozwalają mi zastąpić lokalizacje wyszukiwania na widok jak następująco:

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

w którym %1 otrzymuje z odpowiednim folderze aktywnego najemcy. To działa dobrze tylko jeden problem. Kiedy określić ścieżkę układu na moim zdaniem tak:

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

To rodzaj pokonuje cel o wielowątkowości, ponieważ mam ciężko kodem dokładną lokalizację strony układu. Chcę być w stanie zrobić coś takiego:

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

Gdybym chciał pozwolić najemcy mają swoje strony jeden układ, jak bym go o wspieranie tego?

Próbowałem błahy z metodami widok silników że overrode:

  • CreatePartialView
  • CreateView
  • FileExists

Ale nic nie wydaje się wskazywać się w kierunku bycia w stanie dynamicznie określać strona układu.

Aktualizacja:

Oto co mam działa do tej pory. Kiedyś odpowiedź na to pytanie https://stackoverflow.com/a/9288455/292578 nieznacznie zmodyfikowane, aby utworzyć pomocnika 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."); 
} 

który jest podobny do tego, co sugeruje Saravanan. Następnie można ustawić układ moim zdaniem z tego kodu:

Layout = Html.GetLayoutPageForTenant("_Home"); 

Niestety, ten powiela pracę, że silnik niestandardowy widok robi który wydaje się złym rozwiązaniem.

Odpowiedz

3

Chciałbym zaproponować następujące pojęcia,

W pliku _ViewStart.cshtml, gdzie możemy ustawić stron układu, można użyć coś takiego, z ideą układu url Najemca oparte lub nazwa folderu jest być wypełnione w kontrolerze poprzez pobranie z DB.

@{ 
    Layout = ViewBag.TenantLayoutPageUrl; 
} 

lub

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

Jeśli masz jakieś statyczne reprezentacje danych najemcy, jak statycznym Identity klasy, która będzie śledzić personalizacji najemca, możemy używać, i zminimalizować obie do DB .

Proszę podzielić się pomysł na realizację tego tak, że będzie użyteczny dla społeczności

+0

Jedynym problemem, jaki mam z tym podejściem, jest to, że nie każdy lokator będzie miał własne niestandardowe strony układu. Nadal chcę, aby wyszukiwanie było domyślnym folderem domyślnym, jeśli niestandardowa strona układu nie zostanie znaleziona. – Sparafusile

+0

@Sparafusile: W tym przypadku możemy mieć identyfikator zastępczy w ViewBag. Tak więc w Contollerze sprawdzimy, czy najemca ma niestandardową stronę układu, jeśli tak ustawimy ten folder w torbie widoku, w przeciwnym razie ustawimy nazwę folderu najemcy. 'ViewBag.TenantFolderName =" defaultPath "; if (dzierżawca ma niestandardowy folder) { ViewBag.TenantFolderName = tenantFolderName; } ' IMHO, to będzie bezpieczne. – Saravanan

+0

Chociaż zgadzam się, że to może zadziałać, to w pewnym sensie pokonuje cel silnika widoku niestandardowego, który wykonuje całą pracę w kontrolerze. Będę nadal szukał bardziej eleganckiego rozwiązania. – 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

Można dodać następujące _ViewStart.cshtml w lokatora postrzega folder (~/Views/%1/_ViewStart.cshtml). Każdy lokator może zarządzać własnymi plikami układu.

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

To interesujący pomysł, ale chcę mieć możliwość skorzystania z niestandardowego układu z widokami domyślnymi i/lub użyć domyślnego układu z widokami niestandardowymi. Chyba że źle zrozumiem twoją odpowiedź, nie mogę tego zrobić przy pomocy twojego kodu. – Sparafusile

+0

@Sparafusile Możesz to zrobić, możesz umieścić '_ViewStart.cshtml' w dowolnym folderze, który chcesz dostosować, możesz umieścić go nawet w folderze kontrolera lub w folderze domyślnym. Domyślnie folder kontrolera wyszukiwania Razor Engine dla strony startowej ('_ViewStart.cshtml'), jeśli nie może znaleźć folderu macierzystego i tak dalej, aż do katalogu głównego aplikacji. –

Powiązane problemy