【发布时间】:2017-08-17 13:32:38
【问题描述】:
背景
我正在开发一个 .Net Core API 来驱动歌词应用程序。用户可以注册、提交艺术家和歌词,并在此过程中获得荣誉/XP 积分。基本上是一个社区驱动的歌词网站。
代码
这是我的 ArtistController 类:
[Route("api/artists")]
public class ArtistsController : Controller
{
private readonly IPermissionsService _permissionsService;
private readonly IArtistsService _artistsService;
public ArtistsController(IArtistsService artistsService, IPermissionsService permissionsService)
{
_permissionsService = permissionsService ?? throw new ArgumentNullException(nameof(permissionsService));
_artistsService = artistsService ?? throw new ArgumentNullException(nameof(artistsService));
}
[HttpGet("{slug}")]
[HttpGet("{slug}/lyrics", Name = "GetArtist")]
public async Task<IActionResult> GetArtist(string slug)
{
if (!_artistsService.ArtistExists(slug)) return NotFound();
var permissions = await _permissionsService.GetPermissions(HttpContext);
var artist = _artistsService.GetArtistBySlug(slug, permissions.UserId, permissions.IsAdministrator);
if (artist == null) return NotFound();
return Ok(artist);
}
// other methods omitted
}
本着可测试性的精神,我创建了一个IPermissionsService,这样当我对控制器进行单元测试时,我可以很容易地做到这一点,而不必担心HttpContext和User。
这是PermissionsService类的代码:
public class PermissionsService : IPermissionsService
{
private string _userId;
private bool _isAdministrator;
private HttpContext _httpContext;
private readonly UserManager<BbUser> _userManager;
public PermissionsService(UserManager<BbUser> userManager)
{
_userManager = userManager;
}
public async Task<Permissions> GetPermissions(HttpContext httpContext)
{
_httpContext = httpContext;
PopulateUserIdAndIsAdminFlag();
var permissions = new Permissions
{
UserId = _userId,
IsAdministrator = _isAdministrator
};
return await Task.Run(() => permissions);
}
private async void PopulateUserIdAndIsAdminFlag()
{
if (!IsAuthenticated()) return;
var username = _httpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
var user = await _userManager.FindByNameAsync(username);
var roles = await _userManager.GetRolesAsync(user);
_userId = user.Id;
_isAdministrator = roles.Contains("Admin");
}
private bool IsAuthenticated()
{
return _httpContext.User.Identity.IsAuthenticated;
}
}
问题
当我运行 API 并尝试调用该端点时。我收到以下错误:
在前一个操作完成之前,在此上下文中启动了第二个操作。不保证任何实例成员都是线程安全的。
消息很清楚,但我不知道如何克服这个错误。在将该逻辑移到 PermissionsService 之前,我没有收到错误消息,一切正常!
【问题讨论】:
-
仅供参考:您可以使用
await Task.FromResult(permissions);代替await Task.Run(() => permissions); -
一个比另一个好吗?
-
Task.FromResult立即创建一个已完成的Task对象,因此它不需要创建新线程,所以是的,它更好(在这种情况下)。文档:msdn.microsoft.com/en-us/library/hh194922(v=vs.110).aspx
标签: c# asp.net-core entity-framework-core