2013-05-10 14 views
12

Ben benzer bir çok kiracı görünümü motoru uyguladık: me gibi görünüm için arama yerleri geçersiz izinTaşıma Düzeni özellikleri

Bu: %1 aktif kiracı için doğru klasörü ile ikame edildiği

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

. Bu sadece bir istisna dışında bir sorun çalışıyor. Bu gibi benim görünümünde Düzen yolunu tanımlarken:

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

Biraz sert koduna düzen sayfasının tam yerini beri çok kullanıcılı olma olması amacı yendi.

Ben kiracı onların bir düzen sayfalarını sahip olmasına izin isteseydi
Layout = "~/Views/%1/Shared/_MyLyout.cshtml"; 

, bunu nasıl destek hakkında giderdim: Böyle bir şey yapmak mümkün istiyorum?

ben overrode görünümü motoru yöntemleriyle kurcalıyor denedi:

  • CreatePartialView
  • CreateView
  • FileExists

Ama hiçbir şey dinamik belirtmek mümkün olma yolunda kendini işaret ediyor düzen sayfası.

Güncelleme:

İşte ben bugüne kadar çalışma var zaten. Bu sorunun cevabı biraz HTML yardımcı oluşturmak için modifiye https://stackoverflow.com/a/9288455/292578 kullandı: Saravanan önerdi benzer

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."); 
} 

. Sonra bu kodla Bence düzenini ayarlayabilirsiniz:

Layout = Html.GetLayoutPageForTenant("_Home"); 

Maalesef bu gitmek için yanlış bir yol gibi görünüyor özel görünüm motoru yapıyor işi çoğaltır.

cevap

3

Ben şu fikir önermek istiyorum, biz düzen sayfaları ayarlamak _ViewStart.cshtml dosyasında,

, sen Kiracı dayalı düzen url'nin fikir ya da klasör adıdır ile, böyle bir şey kullanabilirsiniz DB'den getirilerek denetleyicide doldurulur.

@{ 
    Layout = ViewBag.TenantLayoutPageUrl; 
} 

veya

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

Eğer kiracının özelleştirme takip edecek statik Identity sınıf gibi bazı statik Kiracı veri temsillerini varsa, bunu kullanmak ve db'den yuvarlak gezi aza indirebilir .o topluluğun

+0

Bu yaklaşımda sahip olduğum tek sorun, her kiracının kendi özel düzen sayfalarına sahip olmamasıdır. Özel bir mizanpaj sayfası bulunmazsa, aramanın hala Varsayılan klasöre varsayılan olmasını istiyorum. – Sparafusile

+0

@Sparafusile: Bu durumda, ViewBag'da bir geri dönüş kimliğine sahip olabiliriz. Yani, Contoller'da, kiracının özel bir mizanpaj sayfası olup olmadığını kontrol edeceğiz, eğer öyleyse bu klasörü görüntüleme çantasına koyacağız, yoksa kiracının klasör adını ayarlayacağız. 'ViewBag.TenantFolderName =" defaultPath "; (Kiracı özelleştiricisi var ise) { ViewBag.TenantFolderName = tenantFolderName; } IMHO, bu hataya karşı güvenli olacaktır. – Saravanan

+0

Bunun işe yarayabileceğini kabul etsem de, denetleyicideki tüm işleri yapmak için özel görüntü motorunun amacını bozguna uğratır. Daha zarif bir çözüm aramaya devam edeceğim. – Sparafusile

1

deneyin için faydalı olacaktır, böylece

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

Sen kiracı _ViewStart.cshtml Aşağıdaki klasörü (~/Views/%1/_ViewStart.cshtml) görünümleri ekleyebilir, bu uygulanmasına ilişkin fikrinizi paylaşın. Her kiracı kendi düzen dosyalarını yönetebilir.

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

Bu ilginç bir fikir, ancak varsayılan görünümleri olan bir özel düzeni kullanmak ve/veya özel görünümle varsayılan düzeni kullanmak istiyorum. Cevabınızı yanlış anlamadıkça, bunu kodunuzla yapamam. – Sparafusile

+0

@Sparafusile Bunu yapmak için, '_ViewStart.cshtml' öğesini özelleştirmeniz gereken herhangi bir klasöre koyabilirsiniz, denetleyici klasörüne veya varsayılan klasöre yerleştirebilirsiniz. Varsayılan olarak Razor Engine arama denetleyicisi klasörü başlangıç ​​sayfası ('_ViewStart.cshtml') bulunamıyorsa, ana klasör ve benzeri uygulama kökünü bulamaz. –