Web API控制器操作调用两次

Iva*_*ono 5 c# asp.net-web-api

我的控制器动作被调用两次,我无法弄清楚为什么!

这是一个典型的控制器:

[Authorize]
public abstract class BaseController : ApiController
{
    protected readonly ILogService logService;
    protected HttpResponseMessage response = null;

    protected BaseController(ILogService logService)
    {
        this.logService = logService;
    }

    protected override void Initialize(HttpControllerContext controllerContext)
    {
        base.Initialize(controllerContext);

        //check authorization here
    }
}

public abstract class EntityController<T> : BaseController
{
    public EntityController(ILogService logService) : base(logService) { }

    [HttpGet]
    public abstract IHttpActionResult Get(int id);

    [ActionName("Find")]
    [HttpGet]
    public virtual IHttpActionResult Find(string param)
    {
        return null;
    }

    [HttpPost]
    [ValidateModel]
    public abstract IHttpActionResult Create(T dto);

    [HttpPut]
    [ValidateModel]
    public abstract IHttpActionResult Update(T dto);

    [HttpDelete]
    public abstract IHttpActionResult Delete(int id);
}

public class CustomerTypeController : EntityController<CustomerTypeDTO>
{
    private readonly ICustomerTypeService customerTypeService;

    public CustomerTypeController(ILogService logService,
                                  ICustomerTypeService customerTypeService)
        : base(logService)
    {
        this.customerTypeService = customerTypeService;
    }

    public override IHttpActionResult Get(int id)
    {
        var item = Mapper.Map<CustomerTypeDTO>(customerTypeService.Get(id));
        return Ok<CustomerTypeDTO>(item);
    }

    public override IHttpActionResult Find(string param)
    {
        CustomerType modelItem = customerTypeService.Get(x => x.Abbr == param);

        CustomerTypeDTO item = Mapper.Map<CustomerTypeDTO>(modelItem);
        return Ok<CustomerTypeDTO>(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

使用跟踪,我在我的日志文件中找到它:

Request;;;"httpurlhere"/MyWebAPI/CustomerType/Find?param=100
MessageHandlers;ServerCompressionHandler;SendAsync;
Controllers;DefaultHttpControllerSelector;SelectController;Route='controller:CustomerType,action:Find'
Controllers;DefaultHttpControllerSelector;SelectController;CustomerType
Controllers;HttpControllerDescriptor;CreateController;
Controllers;HttpControllerDescriptor;CreateController;MyWebAPI.API.Controllers.Reference.CustomerTypeController
Controllers;CustomerTypeController;ExecuteAsync;
Action;ApiControllerActionSelector;SelectAction;
Action;ApiControllerActionSelector;SelectAction;Selected action 'Find(String param)'
Filters;AuthorizeAttribute;OnAuthorizationAsync;
Filters;AuthorizeAttribute;OnAuthorizationAsync;
ModelBinding;HttpActionBinding;ExecuteBindingAsync;
ModelBinding;ModelBinderParameterBinding;ExecuteBindingAsync;Binding parameter 'param'
ModelBinding;ModelBinderParameterBinding;ExecuteBindingAsync;Parameter 'param' bound to the value '100'
ModelBinding;HttpActionBinding;ExecuteBindingAsync;Model state is valid. Values: param=100
Filters;ValidateModelAttribute;OnActionExecutingAsync;Action filter for 'Find(String param)'
Filters;ValidateModelAttribute;OnActionExecutingAsync;
Action;ApiControllerActionInvoker;InvokeActionAsync;Action='Find(param=100)'
Action;ReflectedHttpActionDescriptor;ExecuteAsync;Invoking action 'Find(param=100)'
Action;ReflectedHttpActionDescriptor;ExecuteAsync;Action returned 'System.Web.Http.Results.OkNegotiatedContentResult`1[MyWebAPI.CustomerTypeDTO]'
Formatting;DefaultContentNegotiator;Negotiate;Type='CustomerType', formatters=[JsonMediaTypeFormatterTracer, XmlMediaTypeFormatterTracer, FormUrlEncodedMediaTypeFormatterTracer, FormUrlEncodedMediaTypeFormatterTracer]
 Formatting;JsonMediaTypeFormatter;GetPerRequestFormatterInstance;Obtaining formatter of type 'JsonMediaTypeFormatter' for type='CustomerType', mediaType='application/json; charset=utf-8'
Formatting;JsonMediaTypeFormatter;GetPerRequestFormatterInstance;Will use same 'JsonMediaTypeFormatter' formatter
Formatting;DefaultContentNegotiator;Negotiate;Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'
Action;ApiControllerActionInvoker;InvokeActionAsync;
Filters;ValidateModelAttribute;OnActionExecutedAsync;Action filter for 'Find(String param)'
Filters;ValidateModelAttribute;OnActionExecutedAsync;
Controllers;CustomerTypeController;ExecuteAsync;
Formatting;JsonMediaTypeFormatter;WriteToStreamAsync;Value='MyWebAPI.CustomerTypeDTO', type='CustomerType', content-type='application/json; charset=utf-8'
Formatting;JsonMediaTypeFormatter;WriteToStreamAsync;
MessageHandlers;ServerCompressionHandler;SendAsync;
Request;;;Content-type='application/json; charset=utf-8', content-length=93
Controllers;CustomerTypeController;Dispose;
Controllers;CustomerTypeController;Dispose;
Run Code Online (Sandbox Code Playgroud)

我检查了客户端,我可以确认该操作仅由客户端请求一次.

编辑:我检查了该特定操作(查找)上数据库被击中的次数,并且它只有一次.

因此,该操作被调用一次,但是,构造函数,其他基类方法和dispose方法总是被调用两次.

为什么会这样?

小智 1

我遇到了完全相同的问题,我的一些控制器操作被调用了两次。我发现这些操作与其他操作之间的唯一区别是这些操作比其他操作花费更多的时间来执行。

我意识到我的客户端代码是这个问题的原因。就我而言,我曾经Volley拨打网络电话。Volley有一些重试调用 Web 服务方法的策略。这意味着如果服务器响应太晚,Volley可以重试调用。默认情况下,Volley如果 1.5 秒内没有得到任何响应,则重试呼叫。我更改了我的客户端代码(Volley 重试策略)并且我的问题得到了解决。这是我所做的更改:

req.setRetryPolicy(new DefaultRetryPolicy(
                   (int) TimeUnit.SECONDS.toMillis(7), //time out before retry
                   0, //number of retries
                   DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
Run Code Online (Sandbox Code Playgroud)

我希望这能有所帮助。