![](/img/trans.png)
[英]Unit testing an AuthorizeAttribute on an ASP.NET Core MVC API controller
[英]Unit testing and multiple parameters to constructors in Asp.Net Core MVC, Passing token to every request
我試圖在Asp.Net Core MVC應用程序中向構造函數添加一個參數,但是這樣做有些困難。 這是我的實現。
登錄操作:
[HttpPost, AllowAnonymous, ValidateAntiForgeryToken]
public IActionResult Login(LoginViewModel loginModel, string returnUrl = null)
{
returnUrl = string.IsNullOrWhiteSpace(returnUrl) ? ApiConstants.Dashboard : returnUrl;
ViewData["ReturnUrl"] = returnUrl;
if (!ModelState.IsValid) return View(loginModel);
var token = Service.Login(loginModel);
if (string.IsNullOrWhiteSpace(token)) return View(loginModel);
TempData["token"] = token;
AddCookie(token);
return RedirectToAction("Index", "Dashboard");
}
private void AddCookie(string token)
{
HttpContext.Response.Cookies.Append("token", token,new CookieOptions()
{
Expires = DateTimeOffset.Now.AddDays(-1)
});
}
控制器:
private readonly INozzleService _nozzleService;
public NozzleController(INozzleService nozzleService)
{
var token = HttpContext.Request.Cookies["token"];
_nozzleService = nozzleService;
}
噴嘴服務:
private static INozzleAdapter Adapter { get; set; }
public NozzleService(INozzleAdapter adapter)
{
Adapter = adapter;
}
噴嘴適配器:
private readonly string _token;
public NozzleAdapter(string token)
{
_token = token;
}
在適配器中獲得令牌后,將令牌添加到HttpClient
標頭中。
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token);
啟動中的ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITempDataProvider, CookieTempDataProvider>();
services.AddDistributedMemoryCache();
services.AddSession();
services.AddTransient<IAccountService, AccountService>();
services.AddTransient<IAccountAdapter, AccountAdapter>();
services.AddTransient<INozzleService, NozzleService>();
services.AddTransient<INozzleAdapter, NozzleAdapter>();
services.AddMvc();
}
您能否讓我知道在Asp.Net core 2.0 MVC應用程序中實現此目標的最佳方法是什么? 我讀過一篇文章,說在Asp.Net Core MVC應用程序中使用多個構造函數不是一個好主意,因此我不想使用多個構造函數。
同時,我想確保所有類都可以使用DI進行單元測試。 這里最好的方法是什么?
如果有人需要更多信息,請告訴我。
更新:
根據Shyju的解決方案,我能夠實現cookie,但是,仍然需要將兩個參數傳遞給我的一個控制器。
private readonly IAccountService _service;
private readonly ITokenProvider _tokenProvider;
public AccountController(IAccountService service, ITokenProvider tokenProvider)
{
_service = service;
_tokenProvider = tokenProvider;
}
因此,可以使用如下所示的AddToken方法。
_tokenProvider.AddToken(token);
您可以考慮抽象邏輯以將令牌獲取到單獨的類,然后根據需要將其注入。
public interface ITokenProvider
{
/// <summary>
/// Gets the token
/// </summary>
/// <returns></returns>
string GetToken();
}
現在創建一個實現,它將從cookie中讀取令牌。 這是一個簡單的實現,它從cookie集合中讀取令牌
public class CookieTokenProvider : ITokenProvider
{
private readonly IHttpContextAccessor httpContextAccessor;
public CookieTokenProvider(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public string GetToken()
{
if (httpContextAccessor.HttpContext.Request.Cookies
.TryGetValue("token", out string tokenValue))
{
return tokenValue;
}
return null;
}
}
現在,您可以將ITokenProvider
實現注入到ITokenProvider
任何位置,並調用GetToken
方法以獲取令牌值。 例如,您可以將其注入NozzleAdapter
類構造函數。
private readonly ITokenProvider tokenProvider;
public NozzleAdapter(ITokenProvider tokenProvider)
{
tokenProvider=tokenProvider;
}
public string SomeOtherMethod()
{
var token = this.tokenProvider.GetToken();
//Do null check and use it
}
確保在Startup類的ConfigureServices
方法中注冊此
services.AddTransient<ITokenProvider, CookieTokenProvider>();
關於您關於獲取令牌和保留令牌的意見,這取決於您要執行的操作。 您可以在CookieTokenProvider
實現中執行此操作。 讀取值並將其存儲在某個地方(本地數據庫,內存緩存等)中,如果存在則從那里獲取(下次)
現在,對於單元測試,您可以創建一個不使用HttpContext的MockTokenProvider,而只需為測試返回一個模擬值,
public class MockTokenProvider : ITokenProvider
{
public string GetToken() => "FakeToken";
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.