0

我有一个 web api 2 控制器:TestController.cs 和一个动作过滤器:TestAuthorizeAttribute.cs

我正在为 Web API 2 项目使用 StructureMap.WebApi2 nuget 包来设置依赖注入。

我正在尝试在 TestController.cs 和 TestAuthorizeAttribute.cs 中创建 TestService 对象的实例。

这是创建 TestService 实例的正确方法吗?

是否有可能多个线程似乎是指 Web API 处理多个同时请求,这些请求以某种方式由同一个 DataContext 处理

请帮助我知道下面提到的代码是否有任何问题。

[RoutePrefix("api/test")]
public class TestController : ApiController
{

public TestController(ITestService testService)

    {
        _testService = testService;            
    }

    /// <summary>
    /// Get details of individual test
    /// </summary>
    /// <param name="Id"> Id</param>
    /// <param name="selectedSection">Selected Section</param>
    /// <returns>Details of the Test</returns>
    [Route("{Id:int}/{selectedSection?}", Name = "TestDetails")]
    [HttpGet]
    [TestAuthorize]
    public HttpResponseMessage Get(int Id, string selectedSection = "")
    {
        var testDetails = _testService.GetTestResults(Id);

        if (scan != null)
        {
            var progress = _testService.GetProgress(scan, user);


            return Request.CreateResponse(HttpStatusCode.OK, scanDetails);
        }
        else
        {
            return Request.CreateResponse(HttpStatusCode.NotFound, new { error = GlobalConstants.ERROR_REVIEW_NOTFOUND });
        }
    }
}


[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class TestAuthorizeAttribute : ActionFilterAttribute
{

      ITestService testService;

    public ScanAuthorizeAttribute()
    {

    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {        
        _testService = actionContext.Request.GetDependencyScope().GetService(typeof(ITestService)) as ITestService;

     var Id = Convert.ToInt32(actionContext.ActionArguments["Id"]);
         var testDetails = _testService.GetTestResults(Id);

    }
4

1 回答 1

0

你在做什么看起来很准确。这几乎正​​是您想要做的。

需要注意的几点:

  1. 假设 ITestService 是 TransientScoped(默认值),您的过滤器和控制器实际上将使用 ITestService 的相同实例。
  2. 如果您的 DataContext 是 TransientScoped,则每个请求都是唯一的(因为 NestedContainer 通过 DependencyScope 存储在请求中),因此您不应该看到您担心的竞争条件。
  3. 据我所知,有一些注意事项。其中之一是 ModelBinders 和 ModelBinderProviders 使用 System.Web.Http.ModelBinding.ModelBinderAttribute 中的此方法进行实例化:

    private static object GetOrInstantiate(HttpConfiguration configuration, Type type)
    {
    return configuration.DependencyResolver.GetService(type) ?? Activator.CreateInstance(type);
    }
    

此方法不使用 DependencyScope,因此此处使用的任何 DBContext 都将是完全唯一的(来自非嵌套容器的 TransientScoped 对象。)

  1. 在 webapi 中处理 IEnumerable 依赖项时,我看到了非常奇怪的竞争条件。StructureMap 使用的默认 IEnumerables 似乎不是线程安全的。
  2. 在过滤器、委托处理程序、模型绑定器等中进行数据访问时要小心。在这些层中引入 N+1 或其他代价高昂的查询可能会造成真正的伤害,因为它们处理的每个请求都会被调用。

关于这方面的任何其他问题请询问,我最近在这方面做了很多事情,所以我对所有这一切都有相当不错的理解。

于 2015-09-28T07:35:15.850 回答