【问题标题】:How to use a controller for a partial view?如何使用控制器进行局部视图?
【发布时间】:2015-05-27 20:52:14
【问题描述】:

我有以下模型。

我需要动态加载左上角的用户配置文件,因此我将 navigation.cshtml 拆分为两个文件。

导航.cshtml

<nav class="navbar-default navbar-static-side" role="navigation">
    <div class="sidebar-collapse">
        <ul class="nav" id="side-menu">
            <li class="nav-header">
                <!-- Top Navbar -->
                @Html.Partial("_Profile")

            </li>
            <li class="@Html.IsSelected(action: "Index")">
                <a href="@Url.Action("Index", "Home")"><i class="fa fa-laptop"></i> <span class="nav-label">Main page</span> </a>
            </li>
            <li class="@Html.IsSelected(action: "Minor")">
                <a href="@Url.Action("Minor", "Home")"><i class="fa fa-desktop"></i> <span class="nav-label">Minor page</span></a>
            </li>
        </ul>
    </div>
</nav>

和profile.cshtml

<div class="dropdown profile-element">
    <span>
        <img alt="image" class="img-circle" src="~/Images/profile_small.jpg" />
    </span>
    <a data-toggle="dropdown" class="dropdown-toggle" href="#">
        <span class="clear">
            <span class="block m-t-xs">
                <strong class="font-bold">David Williams</strong>
            </span> <span class="text-muted text-xs block">Art Director <b class="caret"></b></span>
        </span>
    </a>
    <ul class="dropdown-menu animated fadeInRight m-t-xs">
        <li><a href="@Url.Action("Profile", "AppViews")">Profile</a></li>
        <li><a href="@Url.Action("Contacts", "AppViews")">Contacts</a></li>
        <li><a href="@Url.Action("Inbox", "Mailbox")">Mailbox</a></li>
        <li class="divider"></li>
        <li><a href="@Url.Action("Login", "Pages")">Logout</a></li>
    </ul>
</div>
<div class="logo-element">
    IN+
</div>

我有一个控制器可以返回用户的名字。

 public class UserProfileController : Controller
    {
        // GET: UserProfile
        public async Task<ActionResult> GetPropertiesForUser()
        {
            Uri serviceRoot = new Uri(SettingsHelper.AzureAdGraphApiEndPoint);
            var token = await AppToken.GetAppTokenAsync();

            ActiveDirectoryClient adClient = new ActiveDirectoryClient(
             serviceRoot,
             async () => await AppToken.GetAppTokenAsync());
            string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

            Microsoft.Azure.ActiveDirectory.GraphClient.Application app = (Microsoft.Azure.ActiveDirectory.GraphClient.Application)adClient.Applications.Where(
                a => a.AppId == SettingsHelper.ClientId).ExecuteSingleAsync().Result;
            if (app == null)
            {
                throw new ApplicationException("Unable to get a reference to application in Azure AD.");
            }

            string requestUrl = string.Format("https://graph.windows.net/{0}/users/{1}?api-version=1.5", SettingsHelper.Tenant,ClaimsPrincipal.Current.Identities.First().Name);

            HttpClient hc = new HttpClient();
            hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
                "Bearer", token);

            HttpResponseMessage hrm = await hc.GetAsync(new Uri(requestUrl));

            if (hrm.IsSuccessStatusCode)
            {
                string jsonresult = await hrm.Content.ReadAsStringAsync();
                return View("GetPropertiesForUser", new UserProfile
                {
                    DisplayName = jsonresult //I am still missing here to get the display name only
                });
            }
            else
            {
                return View();
            }
        }

    }

我不知道该怎么做

如何使用带有局部视图的控制器?

更新 1。

我按照以下用户的建议更新了代码:

<nav class="navbar-default navbar-static-side" role="navigation">
    <div class="sidebar-collapse">
        <ul class="nav" id="side-menu">
            <li class="nav-header">
                <!-- Top Navbar -->
          @{ Html.RenderAction("GetPropertiesForUser", "UserProfile"); }
            </li>
            <li class="@Html.IsSelected(action: "Index")">
                <a href="@Url.Action("Index", "Home")"><i class="fa fa-laptop"></i> <span class="nav-label">Main page</span> </a>
            </li>
            <li class="@Html.IsSelected(action: "Minor")">
                <a href="@Url.Action("Minor", "Home")"><i class="fa fa-desktop"></i> <span class="nav-label">Minor page</span></a>
            </li>
        </ul>
    </div>
</nav>


 public class UserProfileController : Controller
    {
        public async Task<ActionResult> GetPropertiesForUser()
        {
            Uri serviceRoot = new Uri(SettingsHelper.AzureAdGraphApiEndPoint);
            var token = await AppToken.GetAppTokenAsync();

            ActiveDirectoryClient adClient = new ActiveDirectoryClient(
             serviceRoot,
             async () => await AppToken.GetAppTokenAsync());
            string userObjectID = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

            Microsoft.Azure.ActiveDirectory.GraphClient.Application app = (Microsoft.Azure.ActiveDirectory.GraphClient.Application)adClient.Applications.Where(
                a => a.AppId == SettingsHelper.ClientId).ExecuteSingleAsync().Result;
            if (app == null)
            {
                throw new ApplicationException("Unable to get a reference to application in Azure AD.");
            }

            string requestUrl = string.Format("https://graph.windows.net/{0}/users/{1}?api-version=1.5", SettingsHelper.Tenant,ClaimsPrincipal.Current.Identities.First().Name);

            HttpClient hc = new HttpClient();
            hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(
                "Bearer", token);

            HttpResponseMessage hrm = await hc.GetAsync(new Uri(requestUrl));

            if (hrm.IsSuccessStatusCode)
            {
                UserProfile up = JsonConvert.DeserializeObject<UserProfile>(await hrm.Content.ReadAsStringAsync());
                return PartialView(up);
                //return View("GetPropertiesForUser", new UserProfile
                //{
                //    DisplayName = up.displayName() //I am still missing here to get the display name only
                //});
            }
            else
            {
                return View();
            }
        }

    }

@model Inspinia_MVC5_Capatech.Models.UserProfile
<div class="dropdown profile-element">
    <span>
        <img a...

但是我得到这个错误: http://screencast.com/t/8VKj4Hwg

局部视图名称称为_Profile.cshtml

【问题讨论】:

    标签: c# asp.net asp.net-mvc asp.net-mvc-4 razor


    【解决方案1】:

    实际上,您需要一个带有 Partial ViewChildAction,因为您希望 GetPropertiesForUser 操作使用 profile.cshtml 视图.

    public class UserProfileController : Controller
    {
       [ChildActionOnly]
       public ActionResult GetPropertiesForUser()
       {
          // ...
         return PartialView(...);
       }
    }
    

    用法

    @Html.Action("GetPropertiesForUser", "UserProfile")
    

    @{ Html.RenderAction("GetPropertiesForUser", "UserProfile"); }
    

    【讨论】:

    • 子动作不能异步... VNext支持异步视图组件,但语法不同。
    【解决方案2】:

    您可以使用 Html.Action 或 Html.RenderAction 来代替 Html.Partial,指向控制器动作。类似的东西:

            <li class="nav-header">
                <!-- Top Navbar -->
                @Html.Action("GetPropertiesForUser")
    

    确保从控制器返回PartialView(),而不是View()

    关于Update 1中的错误,您需要使用命名约定(Action 和 View 之间的共享名称)或指明视图的名称。
    在您的情况下,我认为您需要将返回替换为:

    return PartialView("_Profile");
    

    【讨论】:

    • 我读到一些渲染操作会导致服务器往返两次,对吗?
    • @EstebanV 请提供一个链接 - 渲染子动作没有额外的往返。注意 - 目前尚不清楚您是读错了链接还是完全错误。
    • 在这里,在 cmets 上。 stackoverflow.com/questions/6287015/…
    猜你喜欢
    • 2014-12-25
    • 2017-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多