5

I need to send some values from controller to shared view to show in the top of

    [HttpPost]
    [Route("login")]
    public async Task<ActionResult> Login(LogInRequest logInRequest)
    {
        IEnumerable<UserClaim> UserClaims = null;
        User user = null;
        if (ModelState.IsValid)
        {
      user = await GetUserByEmailAndPassword(logInRequest.UserName, logInRequest.Password);
            if (user.Id != 0)
            {
                 showMenu = await ShowLoanMenu(logInRequest);
                if (showMenu)
                {
        ******** I need to send showMenu and user.Name to shared view
             return RedirectToAction(Constants.Views.SearchView, Constants.Views.LoanDriverController);
                }
            }
               .....
              return View(logInRequest);
    }

I don't want to use TempData, viewdata, viewbag or session, how I can send it by querystring or adding to model.

This is one of the layout:

      <ul>
            <li class="logo">
                <img src="~/Content/Images/logo.png" alt="" />
            </li>
            <li class="nav-item">
                  ***  @if(showmenu is true)
                 {
                    <ul>
                        @Html.ActionLink("Loan Driver", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
                    </ul>
                }
            </li>
        </ul>

and this is another layout:

 <div class="header">
       <div class="master-container">
        <div class="heading">Garage</div>
        <div class="primary-nav">
            <ul>
                <li>******show name of the person</li>
                <li>@Html.ActionLink("Logout", "logout", "Home")</li>
               </ul>
           </div>
        </div>
Alma
  • 3,780
  • 11
  • 42
  • 78
  • You are saying you are not getting the value of `ViewBag.ShowMenu` in the _Layout file even though you set it in your action method ? – Shyju Oct 13 '16 at 22:38
  • Yes, I am not getting value. the view is not view related to that controller, it is in shared view. – Alma Oct 13 '16 at 22:40
  • IS your Login view using the same layout file ? – Shyju Oct 13 '16 at 22:43
  • Yes. and when I debug it goes in it but it is NULL. – Alma Oct 13 '16 at 22:46
  • 2
    Have you tried TempData instead of ViewBag? – chamara Oct 13 '16 at 22:54
  • 1
    @chamara TempData is working great. Thank you. – Alma Oct 13 '16 at 23:07
  • You can also store your data in Session. It depends on your data lifetime and what you going to do with it. – SᴇM Oct 14 '16 at 06:52
  • 1
    TempData looses its value after refresh. – Alma Oct 18 '16 at 15:48
  • Have you tried ViewData["ShowMenu"]? – Tony Oct 18 '16 at 17:23
  • @Alma. Add a claim to the user identity and look for that claim in the view via extension method in order to show the menu. – Nkosi Oct 18 '16 at 17:25
  • @Tony I don't allow to use these. – Alma Oct 18 '16 at 17:29
  • @Alma, if you will be using this in the _layout you can create a base controller class with a ShowMenu property. Have all your controllers that need the property inherit from it. Creating a base class for controllers is pretty common so you may already have one you can modify. – Tony Oct 18 '16 at 17:34
  • To pass values with `RedirectToAction("action", "controller", new { qparam=value })`. You don't show us what `showMenu` is but it may be infeasible to pass on the query string. Also consider this will show in logs as it is passed as a request between the server and client so sensitive data can be read and/or tampered with. A [Child Action](http://stackoverflow.com/questions/12530016/what-is-an-mvc-child-action) is a better way to share view data. – Jasen Oct 18 '16 at 17:56
  • Sure is a whole lot of interesting discussion for a question with a -1 score... maybe some people that are trying to help and not able to answer it should be +1ing it? – Rodger Oct 18 '16 at 23:51
  • Use view models. Start with a base view model class (say `class BaseVM`) that includes properties `bool ShowMenu` and `string UserName` and all you other view models derive from the base class. Then in the layouts(s) use include `@model BaseVM` –  Oct 20 '16 at 05:37
  • You don't want to use TempData, viewdata, viewbag or session OR you are not able to get value using that state management? – Sandip - Frontend Developer Oct 20 '16 at 10:10
  • @Alma are you using Identity for authentication? – Nkosi Oct 25 '16 at 14:17

4 Answers4

1

In your view you can read a value from the querystring like this:

@Request.QueryString["name"]

Then it's just a matter of including the value you want in the querystring which can be handled easily enough when you do a RedirectToAction, like this:

return RedirectToAction("Details", new { id = id, name = "value" })
Rono
  • 3,171
  • 2
  • 33
  • 58
1

I guess you want this for the current request, not for all requests so accepted answer is not the correct way. To share data with views or child controlers within the scope of a single request, easiest way is to put your data to HttpContext.Items. This is shared by all views and child controllers during the same request.

HttpContext.Items["UIOptions"] = new UIOptions { ShowMenu = true }; 

You can abstract this with an extension:

public static class HttpContextExtensions
    {
        public static UIOptions GetUIOptions(this HttpContext httpContext)
        {
            var options = httpContext.Items["UIOptions"] ?? (object) new UIOptions();
            httpContext.Items["UIOptions"] = options;
            return options;
        }
    }

Then in your controller, set options

HttpContext.GetUIOptions().ShowMenu= true

In your view, access it like this:

ViewContext.HttpContext.GetUIOptions()

I usually abstract this further such that you configure it with attributes like

[UIOptions(ShowMenu=true)]
public ActionResult MyAction()
{
    return View();
}

So you write a ActionFilter which checks the attributes on the action and sets the httpContext.GetUIOptions() object's properties using the attribute properties during ActionExecuting phase.

Cagatay Kalan
  • 4,066
  • 1
  • 30
  • 23
0

Create one common/general class and define one public static property over there and set it's value from controller and access it in view as below:

GeneralClass:

public static class GeneralUtility
{
    /// <summary>
    /// Username
    /// </summary>
    public static string Username = "";
}

Controller:

GeneralUtility.Username ="sandip";

View:

@if(GeneralUtility.Username=="sandip")
{
    // rest of the logic
}
  • I think OP is looking for a bool not a string...the user name is always available if the user is authenticated ;) This is a great way to handle it though...I always include a static class in my projects that I can use this way. +1! – BillRuhl Oct 20 '16 at 21:32
  • 2
    If you use a static string to show the username, it will change to every user that login @_@ – Rafael Marques Oct 21 '16 at 18:27
0

You need to pass shared model to your layout. Let say SharedModel The definition of model would be

public class SharedModel
{
  public string Name {get; set;}
  public bool IsLoggedIn {get; set;}
}

All other models will need to be inherited from SharedModel For e.g AccountModel

public class AccountModel : SharedModel
{
  public string Password {get; set;}
  public string Username {get; set;}
}

So when you pass specific model to your view, then shared model will also be passed to your shared layout.

 [HttpPost]
    [Route("login")]
    public async Task<ActionResult> Login(LogInRequest logInRequest)
    {
      AccountModel aM = new AccountModel();
      aM.Name = "Murtaza";
      aM.IsLoggedIn = false;
      ....
      ....
      return View(aM):
     }