ASP.NET MVC'de bir görünüm var mı?


95

Görünümü oluşturmadan önce bir denetleyiciden belirli bir görünüm adının var olup olmadığını belirlemek mümkün müdür?

Oluşturulacak görünümün adını dinamik olarak belirlemem gerekiyor. Bu isimde bir görünüm mevcutsa, o görünümü oluşturmam gerekir. Özel ada göre bir görünüm yoksa, varsayılan bir görünüm oluşturmam gerekir.

Denetleyicimde aşağıdaki koda benzer bir şey yapmak istiyorum:

public ActionResult Index()
{
    var name = SomeMethodToGetViewName();

    // The 'ViewExists' method is what I've been unable to find.
    if (ViewExists(name))
    {
        retun View(name);
    }
    else
    {
        return View();
    }
}

14
Sadece başlığını okurken, çok derin bir felsefi soru gibi görünüyor.

Yanıtlar:


155
 private bool ViewExists(string name)
 {
     ViewEngineResult result = ViewEngines.Engines.FindView(ControllerContext, name, null);
     return (result.View != null);
 }

Kopyala / yapıştır uzantı yöntemi arayanlar için:

public static class ControllerExtensions
{
    public static bool ViewExists(this Controller controller, string name)
    {
        ViewEngineResult result = ViewEngines.Engines.FindView(controller.ControllerContext, name, null);
        return (result.View != null);
    }
}

2
Bu muhtemelen daha iyi. ViewEngines koleksiyonunun dışında bir FindView yöntemi olduğunun farkında değildim.
Lance Harper

1
Ancak görünümün diğer denetleyici için olup olmadığı nasıl kontrol edilir?
SOReader

Bir tür kenara: mühendislerimizden biri (devam ettiğinden beri), verilen değeri bulamazsa bir HttpException (404) atmak için FindView uygulayan özel bir görünüm motoru (MultiTenantViewEngine olarak adlandırılır, böylece amacını anlarsınız) oluşturdu. görünüm. Bu iyi bir uygulama mı? Hiç bir fikrim yok. Ancak bunun gibi başka uygulamalar varsa şaşırmayacaksınız. Bu kod çalışırken görünüm motorunun iç işleyişini bilmeyeceğiniz için, bir catch {return false; } güvende olmak için bu köpeğin etrafında.
Brian Colavito

1
@SOReader, test ettim ama IController denetleyicisi = yeni HomeController (); ve sonra controller.ControllerContext findview yöntemlerine iletebileceğiniz şeyi verecektir.
Vishal Sharma

Bu cevap için teşekkürler. Bana başka bir problemde yardımcı oldu. Görüşümün kısmi olup olmadığını kontrol etmem gerekiyordu ve tüm bölümlerimin adı alt çizgi ile başladığı için çözümümle çalışıp "sonuç.Görünüm! = Boş" olup olmadığını kontrol edebilirim
Deise Vicentin

19

Tek bir görünüm motoru kullandığınızı varsayarak aşağıdakine benzer bir şey denemeye ne dersiniz:

bool viewExists = ViewEngines.Engines[0].FindView(ControllerContext, "ViewName", "MasterName", false) != null;

Görünüşe göre bu, kabul edilen cevaptan 3 dakika önce yayınlandı ve henüz aşk yok mu ?! Benden +1.
Trevor de Koekkoek

@TrevordeKoekkoek ... hmmm ... + 1
Vishal Sharma

8

İşte bunu yapmanın [mutlaka tavsiye edilmeyen] başka bir yolu

 try
 {
     @Html.Partial("Category/SearchPanel/" + Model.CategoryKey)
 }
 catch (InvalidOperationException) { }

bu, bir .cshtml dosyasında kısmi bir görünümün varlığını test etmek içindir. bu soru için gerçekten bir cevap değil, ama buraya bağlanan başka bir soru yanlış kapatıldı, bu yüzden cevabımı burada bırakıyorum
Simon_Weaver

2
Kültüre özgü bir kısmi görünümü kullanmanın bir yolunu aradığım için bu aslında benim kullanımım için belirgindi. Ben de bunu kültüre özgü görünüm adıyla ve ardından catch içinde varsayılan görünümü çağırdım. Ben hiçbir erişim vardı bu yüzden Ve ben, bir fayda fonksiyonuna bu yaptığını ControllerContextolarak FindViewyöntem ihtiyaçları.
korku

2

Bunu, Dave tarafından verilen çözüme dayalı olarak birden fazla denetleyici eyleminde yeniden kullanmak istiyorsanız, aşağıdaki gibi özel bir görünüm sonucu tanımlayabilirsiniz:

public class CustomViewResult : ViewResult
{
    protected override ViewEngineResult FindView(ControllerContext context)
    {
        string name = SomeMethodToGetViewName();

        ViewEngineResult result = ViewEngines.Engines.FindView(context, name, null);

        if (result.View != null)
        {
            return result;
        }

        return base.FindView(context);
    }

    ...
}

Ardından, eyleminizde özel görünümünüzün bir örneğini döndürmeniz yeterlidir:

public ActionResult Index()
{ 
    return new CustomViewResult();
}

1
ViewEngines.Engines.FindView(ViewContext.Controller.ControllerContext, "View Name").View != null

2 sentim.


1

Asp.net core 2.x'te ViewEnginesözellik artık mevcut değil, bu nedenle ICompositeViewEnginehizmeti kullanmamız gerekiyor . Bu, bağımlılık ekleme kullanan kabul edilen cevabın bir çeşidi:

public class DemoController : Controller
{
    private readonly IViewEngine _viewEngine;

    public DemoController(ICompositeViewEngine viewEngine)
    {
        _viewEngine = viewEngine;
    }

    private bool ViewExists(string name)
    {
        ViewEngineResult viewEngineResult = _viewEngine.FindView(ControllerContext, name, true);
        return viewEngineResult?.View != null;
    }

    public ActionResult Index() ...
}

Merak edenler için: Temel arayüz IViewEnginebir hizmet olarak kayıtlı değil, bu yüzden ICompositeViewEngineonun yerine enjekte etmeliyiz . Ancak FindView()yöntem IViewEngine, üye değişkeni temel arayüzü kullanabilmesi için sağlanır.


0

İşte Razor for Core 2.2'de bunu nasıl yapacağınız vb. Çağrının "Find View" değil "GetView" olduğunu unutmayın.

@using Microsoft.AspNetCore.Mvc.ViewEngines
@inject ICompositeViewEngine Engine
...
@if (Engine.GetView(scriptName, scriptName, isMainPage: false).Success) 
{
    @await Html.PartialAsync(scriptName)
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.