MVC 6 - 标题下拉,值可从所有控制器访问?

时间:2016-05-13 13:34:44

标签: asp.net-mvc asp.net-core-mvc

对于MVC来说还是一个新手,我用我认为非常直接的方式遇到了一些绊脚石。

我的_Layout中有一个部分_Header视图。在这里,我想显示一个下拉列表,其中包含根据登录用户填充的项目列表。

在我项目的每个控制器中,我想检索所选的值并显示依赖于此的数据。

我尝试过多次尝试,但仍然陷入不同的位置。我正沿着创建基本控制器的路线来保存我的项目列表和所选项目值(两者都是静态的)。然后,在我的AccountController中,我可以在登录时填充这些值。我可以从其他控制器访问所有这些...但是如何填充我的_Header中的下拉列表?我似乎无法访问这些内容。我甚至走了正确的路线?在经典的ASP中我会将它们存储在viewstate中..

更新 - 根据Marco的建议

从控制器设置的viewbag值在视图中不可用(虽然可访问) - 它总是返回null。我暂时将选择列表更改为一个简单的int,以简化操作。代码

ViewPageBase -

public abstract class ViewPageBase : RazorPage
{
    public int SelectedValue
    {
        get { return (ViewBag.SelectedValue == null ? 0 : ViewBag.SelectedValue); }
        set { ViewBag.SelectedValue = value; }
    }
}

public abstract class ViewPageBase<TModel> : RazorPage<TModel>
{
    public int SelectedValue
    {
        get { return (ViewBag.SelectedValue == null ? 0 : ViewBag.SelectedValue); }
        set { ViewBag.SelectedValue = value; }
    }
}

BaseController -

public class BaseController : Controller
{
    public int SelectedValue
    {
        get { return (ViewBag.SelectedValue == null ? 0 : ViewBag.SelectedValue); }
        set { ViewBag.SelectedValue = value; }
    }
}

AccountController:BaseController -

public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        ViewData["ReturnUrl"] = returnUrl;

        if (!ModelState.IsValid)
            return View(model);

        var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, false);

        if (result.Succeeded)
        {
            SelectedValue = 10;
            _logger.LogInformation(1, "User logged in.");
            return RedirectToLocal(returnUrl);
        }

        if (result.IsLockedOut)
        {
            _logger.LogWarning(2, "User account locked out.");
            return View("Lock");
        }
        ModelState.AddModelError(string.Empty, "Invalid login attempt.");
        return View(model);
    }

_Layout -

@{ await Html.RenderPartialAsync("_Header"); }

在_Header中,我只是想读@SelectedValue但是这总是为null(在我的情况下为0,因为我做了空检查)。

2 个答案:

答案 0 :(得分:0)

您可以使用以下方法

  1. 在局部视图中添加HTML下拉列表。
  2. 编写一个函数,该函数进行ajax调用并获取值,并使用jquery将这些值绑定到下拉列表中。它应该在加载页面时命中服务器(document.ready)。
  3. 现在在您的下拉列表中添加更改事件,并在每次更改时进行ajax调用并在会话中设置所选值。
  4. 所以现在你将在每个控制器上拥有这些选定的值,直到你有会话存在。
  5. 我认为这有帮助。

答案 1 :(得分:0)

您需要创建一个自定义剃刀视图基类,您的所有视图都将从该基类继承。这是关于它是如何完成的文章:

http://haacked.com/archive/2011/02/21/changing-base-type-of-a-razor-view.aspx/

基本上你会创建一个继承自WebViewPage的类。在此课程中,您将声明一个包含选择列表的属性:

public abstract class CustomWebViewPage : WebViewPage
{
    private SelectList _mySelectList;

    public SelectList MySelectList
    {
        get
        {
            try
            {
                _mySelectList = (SelectList)ViewBag.MySelectList;
            }
            catch (Exception)
            {
                _mySelectList = null;
            }
            return _mySelectList;
        }
    }
}

public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel>
{
    private SelectList _mySelectList;

    public SelectList MySelectList
    {
        get
        {
            try
            {
                _mySelectList = (SelectList)ViewBag.MySelectList;
            }
            catch (Exception)
            {
                _mySelectList = null;
            }
            return _mySelectList;
        }
    }
}

正如您所看到的,正在从ViewBag中检索此选择列表的值。它不一定是,但这是我最容易证明这个想法。您可以在所做的基本控制器中设置视图包的值。现在每个视图都可以访问此属性。

您唯一要做的就是告诉您的解决方案使用您的新类构建MVC视图。您可以通过在Web配置中添加以下行来执行此操作:

<pages pageBaseType="Project.Namespace.Views.CustomWebViewPage">

其中Project.Namespace.Views是新自定义类所在的命名空间。请注意,此行位于

<system.web.webPages.razor> 

标签,需要将其添加到与您的视图相关的所有web.configs - Views文件夹中的web.configs。

完成所有这些后,您只需执行以下操作:

@MySelectList
在您的视图中

访问您的选择列表。祝你好运!