1

I have the following mockup.

enter image description here

I need that the user profile on the top left is dinamically loaded, so I splitted the navigation.cshtml into two files.

Navigation.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>

and 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>

and I have one controller that will return the name of the user.

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

    }

The thing I dont know how to do

How can I use a controller with a partial view?

UPDATE 1.

I updated the code as suggested by users below:

<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...

However I get this error: http://screencast.com/t/8VKj4Hwg

The partial view name is called _Profile.cshtml

2 Answers 2

4

Actually you need a ChildAction with Partial View since you want GetPropertiesForUser action to use profile.cshtml view.

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

Usage

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

OR

@{ Html.RenderAction("GetPropertiesForUser", "UserProfile"); }
Sign up to request clarification or add additional context in comments.

1 Comment

Child actions can't be async... VNext support asynchronous view components, but syntax is different.
2

Instead of using Html.Partial you can use Html.Action or Html.RenderAction, pointing to the controller action. Somethign like:

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

Make sure to return PartialView() from the Controller instead of View().

Regarding the error in Update 1, you need to use the naming convention (shared name between Action and View) or indicate the name of the view.
In your case I think you need to replace the return to something like:

return PartialView("_Profile");

3 Comments

I read some that render action would cause 2 rountrips to the server, is that correct?
@EstebanV please provide a link - there is no extra roundtrip to render child actions. Note - it is not clear whether you've read link wrong or it just plain wrong.
here its, on the comments. stackoverflow.com/questions/6287015/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.