MVC3 - render view that is not a method in a controller

不想你离开。 提交于 2019-12-11 14:36:17

问题


I don't know how to best describe my requirement, but here goes. I'm trying to render a view from the following controller/model in a nopCommerce application:

CustomerController.cs snippet:

[NonAction]
protected CustomerNavigationModel GetCustomerNavigationModel(Customer customer)
{
   var model = new CustomerNavigationModel();
   model.HideAvatar = !_customerSettings.AllowCustomersToUploadAvatars;
   model.HideRewardPoints = !_rewardPointsSettings.Enabled;
   model.HideForumSubscriptions = !_forumSettings.ForumsEnabled || !_forumSettings.AllowCustomersToManageSubscriptions;
   model.HideReturnRequests = !_orderSettings.ReturnRequestsEnabled || _orderService.SearchReturnRequests(customer.Id, 0, null).Count == 0;
   model.HideDownloadableProducts = _customerSettings.HideDownloadableProductsTab;
   model.HideBackInStockSubscriptions = _customerSettings.HideBackInStockSubscriptionsTab;
   return model;
}

CustomerNavigationModel.cs:

public partial class CustomerNavigationModel : BaseNopModel
{
    public bool HideInfo { get; set; }
    public bool HideAddresses { get; set; }
    public bool HideOrders { get; set; }
    public bool HideBackInStockSubscriptions { get; set; }
    public bool HideReturnRequests { get; set; }
    public bool HideDownloadableProducts { get; set; }
    public bool HideRewardPoints { get; set; }
    public bool HideChangePassword { get; set; }
    public bool HideAvatar { get; set; }
    public bool HideForumSubscriptions { get; set; }

    public CustomerNavigationEnum SelectedTab { get; set; }
 }

public enum CustomerNavigationEnum
{
    Info,
    Addresses,
    Orders,
    BackInStockSubscriptions,
    ReturnRequests,
    DownloadableProducts,
    RewardPoints,
    ChangePassword,
    Avatar,
    ForumSubscriptions
}

MyAccountNavigation.cshtml snippet:

 @model CustomerNavigationModel
 @using Nop.Web.Models.Customer;
 @if (!Model.HideInfo)
 {
      <li><a href="@Url.RouteUrl("CustomerInfo")" class="@if (Model.SelectedTab == CustomerNavigationEnum.Info)
          {<text>active</text>}
          else
          {<text>inactive</text>}">@T("Account.CustomerInfo")</a></li>}

Views: @Html.Partial("MyAccountNavigation", Model.NavigationModel, new ViewDataDictionary())

I am aware that it is unable to render MyAccountNavigation because it doesn't exist in the controller. However, depending on which page the syntax is placed it works. So is there a way to achieve that without changing the code in the controller? Thanks in advance.


回答1:


MVC looks for the partial view in a specific order. For your partial view to work, you need to place MyAccountNavigation.cshtml' into~/Views/Shared/`

I've looked at the source and this is what happens:

 public RazorViewEngine(IViewPageActivator viewPageActivator)
            : base(viewPageActivator)
        {
            AreaViewLocationFormats = new[]
            {
                "~/Areas/{2}/Views/{1}/{0}.cshtml",
                "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                "~/Areas/{2}/Views/Shared/{0}.cshtml",
                "~/Areas/{2}/Views/Shared/{0}.vbhtml"
            };
            AreaMasterLocationFormats = new[]
            {
                "~/Areas/{2}/Views/{1}/{0}.cshtml",
                "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                "~/Areas/{2}/Views/Shared/{0}.cshtml",
                "~/Areas/{2}/Views/Shared/{0}.vbhtml"
            };
            AreaPartialViewLocationFormats = new[]
            {
                "~/Areas/{2}/Views/{1}/{0}.cshtml",
                "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                "~/Areas/{2}/Views/Shared/{0}.cshtml",
                "~/Areas/{2}/Views/Shared/{0}.vbhtml"
            };

            ViewLocationFormats = new[]
            {
                "~/Views/{1}/{0}.cshtml",
                "~/Views/{1}/{0}.vbhtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/Shared/{0}.vbhtml"
            };
            MasterLocationFormats = new[]
            {
                "~/Views/{1}/{0}.cshtml",
                "~/Views/{1}/{0}.vbhtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/Shared/{0}.vbhtml"
            };
            PartialViewLocationFormats = new[]
            {
                "~/Views/{1}/{0}.cshtml",
                "~/Views/{1}/{0}.vbhtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/Shared/{0}.vbhtml"
            };

            FileExtensions = new[]
            {
                "cshtml",
                "vbhtml",
            };
        }

We are interested in AreaPartialViewLocationFormats and PartialViewLocationFormats.

This explains why your view is found when you try to use it within Customer related views, and it doesn't work anywhere else.




回答2:


Whatever I understand from your question is you need to execute "MyAccountNavigation" partial view from many pages and for that you can put this partial view in Shared folder.

Please correct me if I am wrong.

Edited text

BaseController :

ExcecuteCore method

you can store your menu or that model in ViewBag like

var customerNavigationModel = assigned your value;
ViewBag.MenuData = customerNavigationModel;

From view

@{Html.RenderPartial("MyAccountNavigation", ViewBag.MenuData);}


来源:https://stackoverflow.com/questions/12346274/mvc3-render-view-that-is-not-a-method-in-a-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!