Kết xuất một phần từ thư mục khác nhau (không chia sẻ)


256

Làm cách nào tôi có thể có chế độ xem hiển thị một phần (điều khiển người dùng) từ một thư mục khác? Với bản xem trước 3 tôi đã từng gọi RenderUserControl với đường dẫn đầy đủ, nhưng với việc nâng cấp lên bản xem trước 5 thì điều này là không thể nữa. Thay vào đó, chúng tôi có phương thức RenderPartial, nhưng nó không cung cấp cho tôi chức năng mà tôi đang tìm kiếm.

Câu trả lời:


443

Chỉ cần bao gồm đường dẫn đến dạng xem, với phần mở rộng tệp.

Dao cạo:

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

Công cụ ASP.NET:

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

Nếu đó không phải là vấn đề của bạn, bạn có thể vui lòng bao gồm mã đã sử dụng để làm việc với RenderUserControl không?


19
Tôi ước chúng ta có thể nói / AnotherFolder / Tin nhắn
Simon_Weaver

4
@Simon_Weaver Bạn có thể đạt được điều đó. Một cách sẽ là sửa đổi ViewEngine và ghi đè FindPartialViewphương thức của nó bằng một cái gì đó nhưif(partialViewName.Contains"/")partialViewName="~/Views/"+partialViewName;
Arnis Lapsa

2
Hoạt động trong công cụ dao động MVC 3 là tốt, nhưng giống như ở trên, bạn cần phần mở rộng (.cshtml).
Chris

Nếu nó khác nhau, bạn sẽ cần đưa ra đường dẫn "~ / Area / TestArea / Views / Shared / _SomePartial.mobile.cshtml"
sandeep Talabathula

Làm thế nào để bạn xử lý các nền văn hóa khác nhau của chế độ xem một phần đó (ví dụ ~ / Lượt xem / AnotherFolder / Messages.en.cshtml)?
jasdefer

29

Trong trường hợp của tôi, tôi đã sử dụng MvcMailer (https://github.com/smsohan/MvcMailer) và muốn truy cập chế độ xem một phần từ thư mục khác, không có trong "Được chia sẻ". Các giải pháp trên không hoạt động, nhưng sử dụng một đường dẫn tương đối thì có.

@Html.Partial("../MyViewFolder/Partials/_PartialView", Model.MyObject)

Tương tự @ Html.Partial ("../ Shared / _PartialView") để sử dụng thư mục Shared.
Curtis Yallop

11
Tôi thấy rằng điều này không hoạt động mà không có phần mở rộng .cshtml ở cuối.
Lu-ca

28

Nếu bạn đang sử dụng đường dẫn khác này nhiều lần bạn có thể sửa lỗi này vĩnh viễn mà không phải chỉ định đường dẫn mọi lúc. Theo mặc định, nó đang kiểm tra các chế độ xem một phần trong thư mục Xem và trong thư mục Dùng chung. Nhưng nói rằng bạn muốn thêm một.

Thêm một lớp vào thư mục Mô hình của bạn:

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();
   }
}

Sau đó, trong tệp Global.asax.cs của bạn, thêm dòng sau:

ViewEngines.Engines.Add(new NewViewEngine());

6
Tất nhiên tôi nhận ra câu hỏi này đã được hỏi từ lâu. Tôi nghĩ tôi sẽ thêm nó cho nhân viên Google trong tương lai và Bingers tương lai.
Paul

- Không hoạt động trong .Net Core 2.2, vì RazorViewEngine.PartialViewLocationFormats không tồn tại.
Demian Berisford-Maynard

7

Đối với điều khiển người dùng có tên myPartial.ascx nằm trong thư mục Lượt xem / Tài khoản, hãy viết như sau:

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

5

Tôi đã tạo ra một cách giải quyết có vẻ như đang hoạt động khá tốt. Tôi thấy cần phải chuyển sang ngữ cảnh của một bộ điều khiển khác để tra cứu tên hành động, tra cứu xem, v.v. Để thực hiện điều này, tôi đã tạo một phương thức mở rộng mới cho HtmlHelper:

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

ControllerContextRegion được định nghĩa là:

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;
    }
}

Cách thức này được sử dụng trong một khung nhìn như sau:

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

Có thể có các tác dụng phụ không mong muốn cho việc này nếu mã của bạn yêu cầu controllerthành phần tuyến đường không thay đổi, nhưng trong mã của chúng tôi cho đến nay, dường như không có bất kỳ tiêu cực nào đối với phương pháp này.


4

VirtualPathProviderViewEngine, dựa trên WebFormsViewEngine, được cho là hỗ trợ các ký tự "~" và "/" ở phía trước đường dẫn để các ví dụ trên của bạn hoạt động.

Tôi nhận thấy các ví dụ của bạn sử dụng đường dẫn "~ / Account / myPartial.ascx", nhưng bạn đã đề cập rằng kiểm soát người dùng của bạn nằm trong thư mục Lượt xem / Tài khoản. Bạn đã thử chưa

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

hoặc đó chỉ là một lỗi đánh máy trong câu hỏi của bạn?



0

bạn nên thử cái này

~/Views/Shared/parts/UMFview.ascx

đặt ~/Views/mã trước


0

Tạo Công cụ xem tùy chỉnh và có một phương thức trả về ViewEngineResult Trong ví dụ này, bạn chỉ cần ghi đè lên _options.ViewLocationFormatsvà thêm thư mục thư mục của bạn:

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

Ví dụ: https://github.com/AspNetMonsters/pugzor


-5

Hãy thử sử dụng RenderAction("myPartial","Account");


3
Xin vui lòng Đọc câu hỏi khi người dùng đang hỏi về chế độ xem trong thư mục khác nhau, thư mục trong mã của bạn ở đâu?
Pamma
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.