Render parsial dari folder yang berbeda (tidak dibagikan)

256

Bagaimana saya dapat memiliki tampilan membuat sebagian (kontrol pengguna) dari folder yang berbeda? Dengan pratinjau 3, saya biasa memanggil RenderUserControl dengan jalur lengkap, tetapi dengan memutakhirkan ke pratinjau 5 ini tidak mungkin lagi. Alih-alih, kami mendapatkan metode RenderPartial, tetapi itu tidak menawarkan fungsionalitas yang saya cari.

Boris Callens
sumber

Jawaban:

443

Cukup sertakan jalur ke tampilan, dengan ekstensi file.

Pisau cukur:

@Html.Partial("~/Views/AnotherFolder/Messages.cshtml", ViewData.Model.Successes)

Mesin ASP.NET:

<% Html.RenderPartial("~/Views/AnotherFolder/Messages.ascx", ViewData.Model.Successes); %>

Jika itu bukan masalah Anda, bisakah Anda memasukkan kode Anda yang dulu berfungsi dengan RenderUserControl?

Elijah Manor
sumber
19
Saya berharap kita bisa mengatakan / AnotherFolder / Pesan
Simon_Weaver
4
@Simon_Weaver Anda bisa mencapainya. Salah satu caranya adalah dengan memodifikasi ViewEngine dan mengganti FindPartialViewmetodenya dengan sesuatu sepertiif(partialViewName.Contains"/")partialViewName="~/Views/"+partialViewName;
Arnis Lapsa
2
Bekerja di mesin Razor MVC 3 juga, tetapi seperti di atas, Anda memerlukan ekstensi (.cshtml).
Chris
Jika di bawah yang berbeda, Anda perlu memberikan path "~ / Areas / TestArea / Views / Shared / _SomePartial.mobile.cshtml"
sandeep talabathula
Bagaimana Anda menangani budaya yang berbeda dari tampilan parsial itu (misalnya ~ / Tampilan / AnotherFolder / Messages.en.cshtml)?
jasdefer
29

Dalam kasus saya, saya menggunakan MvcMailer (https://github.com/smsohan/MvcMailer) dan ingin mengakses sebagian tampilan dari folder lain, yang tidak ada di "Dibagikan." Solusi di atas tidak berfungsi, tetapi menggunakan jalur relatif tidak.

@Html.Partial("../MyViewFolder/Partials/_PartialView", Model.MyObject)
Aaron Sherman
sumber
Demikian pula @ Html.Partial ("../ Shared / _PartialView") untuk menggunakan folder Shared.
Curtis Yallop
11
Saya menemukan bahwa ini tidak akan berfungsi tanpa ekstensi .cshtml di akhir.
Lukas
28

Jika Anda menggunakan jalur lain ini banyak waktu, Anda dapat memperbaikinya secara permanen tanpa harus menentukan jalur sepanjang waktu. Secara default, ini memeriksa tampilan sebagian di folder Lihat dan di folder Bersama. Tetapi katakan Anda ingin menambahkan satu.

Tambahkan kelas ke folder Model Anda:

public class NewViewEngine : RazorViewEngine {

   private static readonly string[] NEW_PARTIAL_VIEW_FORMATS = new[] {
      "~/Views/Foo/{0}.cshtml",
      "~/Views/Shared/Bar/{0}.cshtml"
   };

   public NewViewEngine() {
      // Keep existing locations in sync
      base.PartialViewLocationFormats = base.PartialViewLocationFormats.Union(NEW_PARTIAL_VIEW_FORMATS).ToArray();
   }
}

Kemudian di file Global.asax.cs Anda, tambahkan baris berikut:

ViewEngines.Engines.Add(new NewViewEngine());
Paul
sumber
6
Tentu saja saya menyadari pertanyaan ini sudah lama ditanyakan. Kupikir aku akan menambahkannya untuk Googler dan Bingers masa depan.
Paul
- Tidak akan bekerja di .Net Core 2.2, karena RazorViewEngine.PartialViewLocationFormats tidak ada.
Demian Berisford-Maynard
7

Untuk kontrol pengguna bernama myPartial.ascx yang terletak di folder Views / Account, tulis seperti ini:

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>
Rahatur
sumber
5

Saya telah membuat solusi yang tampaknya bekerja cukup baik. Saya menemukan kebutuhan untuk beralih ke konteks pengontrol yang berbeda untuk pencarian nama tindakan, melihat pencarian, dll. Untuk menerapkan ini, saya membuat metode ekstensi baru untuk HtmlHelper:

public static IDisposable ControllerContextRegion(
    this HtmlHelper html, 
    string controllerName)
{
    return new ControllerContextRegion(html.ViewContext.RouteData, controllerName);
}

ControllerContextRegion didefinisikan sebagai:

internal class ControllerContextRegion : IDisposable
{
    private readonly RouteData routeData;
    private readonly string previousControllerName;

    public ControllerContextRegion(RouteData routeData, string controllerName)
    {
        this.routeData = routeData;
        this.previousControllerName = routeData.GetRequiredString("controller");
        this.SetControllerName(controllerName);
    }

    public void Dispose()
    {
        this.SetControllerName(this.previousControllerName);
    }

    private void SetControllerName(string controllerName)
    {
        this.routeData.Values["controller"] = controllerName;
    }
}

Cara ini digunakan dalam tampilan adalah sebagai berikut:

@using (Html.ControllerContextRegion("Foo")) {
    // Html.Action, Html.Partial, etc. now looks things up as though
    // FooController was our controller.
}

Mungkin ada efek samping yang tidak diinginkan untuk ini jika kode Anda mengharuskan controllerkomponen rute untuk tidak berubah, tetapi dalam kode kami sejauh ini, tampaknya tidak ada negatif untuk pendekatan ini.

Yakub
sumber
4

VirtualPathProviderViewEngine, yang menjadi dasar WebFormsViewEngine, seharusnya mendukung karakter "~" dan "/" di depan jalan sehingga contoh Anda di atas harus bekerja.

Saya perhatikan contoh Anda menggunakan jalur "~ / Akun / myPartial.ascx", tetapi Anda menyebutkan bahwa kontrol pengguna Anda ada di folder Views / Akun. Sudahkah Anda mencoba

<%Html.RenderPartial("~/Views/Account/myPartial.ascx");%>

atau itu hanya kesalahan ketik dalam pertanyaan Anda?

Andrew Stanton-Perawat
sumber
0

Anda harus mencoba ini

~/Views/Shared/parts/UMFview.ascx

tempatkan ~/Views/sebelum kode Anda

mounir
sumber
0

Buat Custom View Engine dan memiliki metode yang mengembalikan ViewEngineResult Dalam contoh ini Anda hanya menimpa _options.ViewLocationFormatsdan menambahkan direktori folder Anda:

public ViewEngineResult FindView(ActionContext context, string viewName, bool isMainPage)
        {
            var controllerName = context.GetNormalizedRouteValue(CONTROLLER_KEY);
            var areaName = context.GetNormalizedRouteValue(AREA_KEY);

            var checkedLocations = new List<string>();
            foreach (var location in _options.ViewLocationFormats)
            {
                var view = string.Format(location, viewName, controllerName);
                if (File.Exists(view))
                {
                    return ViewEngineResult.Found("Default", new View(view, _ViewRendering));
                }
                checkedLocations.Add(view);
            }

            return ViewEngineResult.NotFound(viewName, checkedLocations);
        }

Contoh: https://github.com/AspNetMonsters/pugzor

Demian Berisford-Maynard
sumber
-5

Coba gunakan RenderAction("myPartial","Account");

Siva Kandaraj
sumber
3
Baca pertanyaan saat pengguna bertanya tentang tampilan di folder berbeda di mana folder dalam kode Anda?
Pamma