簡體   English   中英

有沒有一種方法可以將DbContext實例從控制器傳遞到ActionFilter?

[英]Is there a way to pass an instance of DbContext from the controller to an ActionFilter?

我在ASP.NET MVC 5框架的頂部有一個使用c#編寫的應用程序。

我通過繼承ActionFilterAttribute類創建了一個自定義動作過濾器(即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();
    }
}

這是我的動作過濾器類

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 Identity的子集。

使用OWIN中間件的主要優點是可以使用ASP.NET MVC附帶的Authorize屬性。 實施比您想象的要容易得多。

示例代碼-

OWIN認證中間件

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "ApplicationCookie",
            LoginPath = new PathString("/Account/Login")
        });
    }
}

將訪問權限存儲為Principle對象中的角色聲明

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM