有没有办法将 DbContext 的实例从控制器传递到 ActionFilter?
Is there a way to pass an instance of DbContext from the controller to an ActionFilter?
我有一个在 ASP.NET MVC 5 框架之上使用 c# 编写的应用程序。
我通过继承 ActionFilterAttribute
class 创建了一个自定义操作过滤器(即 ValidateCookieValueAction
)。我为我的多个操作方法使用 ValidateCookieValueAction
属性。
过滤器的目的是确保用户在允许他们进行操作之前拥有 cookie 值。尽管存在安全问题,但该过滤器的效果很好。但是,cookie 值本身需要在用户进入之前进行验证。
为了验证 cookie 值,我需要一个 DbContext
的实例,这样我就可以查询数据库并验证 cookie 值。
我知道我可以直接在 ActionFilter 中创建 DbContext
的新实例。但是,我想要那个。我希望能够传递我已经从控制器创建的 DbContext
实例,以允许我重用我已经在控制器中建立的连接。
这是我的控制器设置方式
public class BaseController
{
protected IDbContext Context { get; private set; }
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
Context = new DbContext();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Context.Dispose();
}
base.Dispose(disposing);
}
}
public class TestController : BaseController
{
[ValidateCookieValueAction]
public ActionResult Index()
{
// the uses is in!
return View();
}
}
这是我的动作过滤器class
public class ValidateCookieValueAction : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
var cookie = new CookieJar(filterContext.HttpContext);
if (!cookie.Has(ContactListCookieName))
{
var Url = new UrlHelper(filterContext.RequestContext);
var url = Url.Action("Guest", "Test");
filterContext.Result = new RedirectResult(url);
}
}
}
如何将 Context
的实例传递给 ValidateCookieValueAction
?
这与原始问题没有直接关系,但看起来您是在自己创建一个身份验证机制。如果没有,请告诉我;我会删除这个答案。
ASP.NET已经有了ASP.NET身份比自己创建更安全可靠.但是,如果您想使用现有的自定义表,您可以使用 OWIN 中间件,它基本上是 ASP.NET 身份的一个子集。
使用 OWIN 中间件的主要优点是您可以使用 Authorize 属性与 ASP.NET MVC。实施比您想象的要容易得多。
示例代码-
OWIN Authentication Middle-ware
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/Account/Login")
});
}
}
Store access as role claim in Principle object
public void SignIn(User user, IList<string> roleNames)
{
IList<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Sid, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.GivenName, user.FirstName),
new Claim(ClaimTypes.Surname, user.LastName),
};
foreach (string roleName in roleNames)
{
claims.Add(new Claim(ClaimTypes.Role, roleName));
}
ClaimsIdentity identity = new ClaimsIdentity(claims, AuthenticationType);
IOwinContext context = _context.Request.GetOwinContext();
IAuthenticationManager authenticationManager = context.Authentication;
authenticationManager.SignIn(identity);
}
用法
[Authorize(Roles = "CanViewHome")]
public class IndexController : Controller
{
[Authorize(Roles = "CanEditHome")]
public ActionResult Edit()
{
return View();
}
}
默认情况下,当前上下文中已经存储了一个上下文。
在 Startup.Configuration(IAppBuilder 应用程序)中
app.CreatePerOwinContext(ApplicationDbContext.Create); // this already stores a DbContext
您可以使用
获取它
var dbContext = HttpContext.GetOwinContext().Get<ApplicationDbContext>();
或者,您可以将上下文存储在 [TempData] 或 [Session] 中。
如果您在同一个请求中重新获取它,那么只需将 DbContext 扔到 Context.Items[] 中,这些仅适用于当前请求。
在 OnActionExecuting 中:
filterContext.Controller.TempData
在控制器中:
this.TempData
我有一个在 ASP.NET MVC 5 框架之上使用 c# 编写的应用程序。
我通过继承 ActionFilterAttribute
class 创建了一个自定义操作过滤器(即 ValidateCookieValueAction
)。我为我的多个操作方法使用 ValidateCookieValueAction
属性。
过滤器的目的是确保用户在允许他们进行操作之前拥有 cookie 值。尽管存在安全问题,但该过滤器的效果很好。但是,cookie 值本身需要在用户进入之前进行验证。
为了验证 cookie 值,我需要一个 DbContext
的实例,这样我就可以查询数据库并验证 cookie 值。
我知道我可以直接在 ActionFilter 中创建 DbContext
的新实例。但是,我想要那个。我希望能够传递我已经从控制器创建的 DbContext
实例,以允许我重用我已经在控制器中建立的连接。
这是我的控制器设置方式
public class BaseController
{
protected IDbContext Context { get; private set; }
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
Context = new DbContext();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Context.Dispose();
}
base.Dispose(disposing);
}
}
public class TestController : BaseController
{
[ValidateCookieValueAction]
public ActionResult Index()
{
// the uses is in!
return View();
}
}
这是我的动作过滤器class
public class ValidateCookieValueAction : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
var cookie = new CookieJar(filterContext.HttpContext);
if (!cookie.Has(ContactListCookieName))
{
var Url = new UrlHelper(filterContext.RequestContext);
var url = Url.Action("Guest", "Test");
filterContext.Result = new RedirectResult(url);
}
}
}
如何将 Context
的实例传递给 ValidateCookieValueAction
?
这与原始问题没有直接关系,但看起来您是在自己创建一个身份验证机制。如果没有,请告诉我;我会删除这个答案。
ASP.NET已经有了ASP.NET身份比自己创建更安全可靠.但是,如果您想使用现有的自定义表,您可以使用 OWIN 中间件,它基本上是 ASP.NET 身份的一个子集。
使用 OWIN 中间件的主要优点是您可以使用 Authorize 属性与 ASP.NET MVC。实施比您想象的要容易得多。
示例代码-
OWIN Authentication Middle-ware
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/Account/Login")
});
}
}
Store access as role claim in Principle object
public void SignIn(User user, IList<string> roleNames)
{
IList<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Sid, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.GivenName, user.FirstName),
new Claim(ClaimTypes.Surname, user.LastName),
};
foreach (string roleName in roleNames)
{
claims.Add(new Claim(ClaimTypes.Role, roleName));
}
ClaimsIdentity identity = new ClaimsIdentity(claims, AuthenticationType);
IOwinContext context = _context.Request.GetOwinContext();
IAuthenticationManager authenticationManager = context.Authentication;
authenticationManager.SignIn(identity);
}
用法
[Authorize(Roles = "CanViewHome")]
public class IndexController : Controller
{
[Authorize(Roles = "CanEditHome")]
public ActionResult Edit()
{
return View();
}
}
默认情况下,当前上下文中已经存储了一个上下文。
在 Startup.Configuration(IAppBuilder 应用程序)中
app.CreatePerOwinContext(ApplicationDbContext.Create); // this already stores a DbContext
您可以使用
获取它var dbContext = HttpContext.GetOwinContext().Get<ApplicationDbContext>();
或者,您可以将上下文存储在 [TempData] 或 [Session] 中。
如果您在同一个请求中重新获取它,那么只需将 DbContext 扔到 Context.Items[] 中,这些仅适用于当前请求。
在 OnActionExecuting 中:
filterContext.Controller.TempData
在控制器中:
this.TempData