Asp.net mvc 如何在ASP.NET MVC 5中的一个位置设置用户数据

Asp.net mvc 如何在ASP.NET MVC 5中的一个位置设置用户数据,asp.net-mvc,Asp.net Mvc,这个代码变得多余了 public class CompanyController : Controller { private ApplicationDbContext _dbContext; //private ApplicationUser _applicationUser; public CompanyController()

这个代码变得多余了

        public class CompanyController : Controller
        {
                    private ApplicationDbContext _dbContext;
                    //private ApplicationUser _applicationUser;

                    public CompanyController()
                    {
                        _dbContext = new ApplicationDbContext();

                       //I could have set _applicationUser here with
                       //_applicationUser = _dbContext.Users.Find(User.Identity.GetUserId()); 
                       //but User object is not yet avaialbe in constructor
                    }

                    public ActionResult Index()
                    {
                        var user = _dbContext.Users.Find(User.Identity.GetUserId());
                        ViewBag.Title = "Company Details";

                       //process user here

                        return View();
                    }

                   public ActionResult Page()
                    {
                        var user = _dbContext.Users.Find(User.Identity.GetUserId());
                        ViewBag.Title = "Page Details";

                       //process user here

                        return View();
                    }

                  // and I still have many ActionResult that needs user object
        }

我想知道如何在控制器的一个区域中设置用户对象,这样我就不必在每次操作中重复它,因为构造函数部分不在选项中。

一旦登录,您可以在会话中存储对象:

var user = _dbContext.Users.Find(User.Identity.GetUserId());
然后从会话中提取用户的详细信息。我通常会将其包装在一个公共实用程序中,以便在需要时更改底层存储结构,甚至在会话死亡时(通过从身份验证cookie中提取用户信息)重新填充会话(如果有用的话)。。。这取决于您的用例

您甚至可以创建一个自定义ASP.NET控制器基类,并在其中添加用户属性,从而将当前用户拉入。只要您的所有控制器都继承自该类,就可以访问该类:

var user = _dbContext.Users.Find(User.Identity.GetUserId());
HttpContext.Session["CurrentUser"] = user;

将DB代码或会话替代项放入其中并返回用户将使其在整个过程中都可访问。

登录后,您可以在会话中存储对象:

var user = _dbContext.Users.Find(User.Identity.GetUserId());
然后从会话中提取用户的详细信息。我通常会将其包装在一个公共实用程序中,以便在需要时更改底层存储结构,甚至在会话死亡时(通过从身份验证cookie中提取用户信息)重新填充会话(如果有用的话)。。。这取决于您的用例

您甚至可以创建一个自定义ASP.NET控制器基类,并在其中添加用户属性,从而将当前用户拉入。只要您的所有控制器都继承自该类,就可以访问该类:

var user = _dbContext.Users.Find(User.Identity.GetUserId());
HttpContext.Session["CurrentUser"] = user;

将DB代码或会话替代项放入其中并返回用户将使其在整个过程中都可访问。

您可以使用自定义的
IControllerFactory
将此通用代码放在一个位置(使其干燥)。与自定义的
IUserEntityInjectable
接口相结合,它只能注入到需要它的控制器上,并消除了为此使用基类的任何缺陷。注意,我在这里使用了名称
UserEntity
,因为控制器类已经有了
User
属性,所以我们需要一个不同的名称

public abstract class BaseController : Controller
{
   public User User { get { .. } };
}
用法 只需在您的自定义
IControllerFactory

public interface IUserEntityInjectable
{
    User UserEntity { get; set; }
}

public class UserEntityInjector : DefaultControllerFactory
{
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controller = base.CreateController(requestContext, controllerName);

        if (controller is IUserEntityInjectable)
        {
            using (var dbContext = new ApplicationDbContext())
            {
                ((IUserEntityInjectable)controller).UserEntity = dbContext.Users.Find(requestContext.HttpContext.User.Identity.GetUserId());
            }
        }

        return controller;
    }
}
然后,只需在需要它的控制器上实现
IUserEntityInjectable

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        ControllerBuilder.Current.SetControllerFactory(new UserEntityInjector());
    }
}
如果(且仅当)
IUserEntityInjectable
在控制器中实现,则将自动查找并填充
用户
实体


如果需要更细粒度的控制,可以实现
ActionFilterAttribute
,通过使用自定义属性装饰操作,仅在特定操作上填充用户。

可以使用自定义
IControllerFactory
将此通用代码放在一个位置(使其干燥)。与自定义的
IUserEntityInjectable
接口相结合,它只能注入到需要它的控制器上,并消除了为此使用基类的任何缺陷。注意,我在这里使用了名称
UserEntity
,因为控制器类已经有了
User
属性,所以我们需要一个不同的名称

public abstract class BaseController : Controller
{
   public User User { get { .. } };
}
用法 只需在您的自定义
IControllerFactory

public interface IUserEntityInjectable
{
    User UserEntity { get; set; }
}

public class UserEntityInjector : DefaultControllerFactory
{
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controller = base.CreateController(requestContext, controllerName);

        if (controller is IUserEntityInjectable)
        {
            using (var dbContext = new ApplicationDbContext())
            {
                ((IUserEntityInjectable)controller).UserEntity = dbContext.Users.Find(requestContext.HttpContext.User.Identity.GetUserId());
            }
        }

        return controller;
    }
}
然后,只需在需要它的控制器上实现
IUserEntityInjectable

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        ControllerBuilder.Current.SetControllerFactory(new UserEntityInjector());
    }
}
如果(且仅当)
IUserEntityInjectable
在控制器中实现,则将自动查找并填充
用户
实体


如果您需要更细粒度的控制,可以实现
ActionFilterAttribute
,通过使用自定义属性修饰操作,仅在特定操作上填充用户。

感谢您的回答,当我使用
var user=UserEntity时,我无法解析IPrincAlinjectables
然后访问用户属性
user.Company
I get
ObjectContext实例已被释放,无法再用于需要连接的操作,因为在您调用控制器内的属性时,dbContext已被释放。或者,您可以创建一个
IDbContextInjectable
接口,并使用类似的技术将其注入控制器,以便建立“实时”连接。在调用
base.ReleaseController
之前,您必须重写控制器工厂中的
ReleaseController
方法,并在dbContext上调用
Dispose()
方法。感谢您的回答,当我使用
var user=UserEntity时,我无法解析IPrincAlinjectables
然后访问用户属性
user.Company
I get
ObjectContext实例已被释放,无法再用于需要连接的操作,因为在您调用控制器内的属性时,dbContext已被释放。或者,您可以创建一个
IDbContextInjectable
接口,并使用类似的技术将其注入控制器,以便建立“实时”连接。在调用
base.ReleaseController
之前,您必须重写控制器工厂中的
ReleaseController
方法,并在dbContext上调用
Dispose()
方法。