Web API控制器操作调用两次

时间:2014-10-31 10:06:34

标签: 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);
    }
}

使用跟踪,我在日志文件中找到了这个:

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;

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

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

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

为什么会这样?

1 个答案:

答案 0 :(得分:0)

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

我意识到我的客户代码是造成此问题的原因。就我而言,我使用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));

我希望这会有所帮助。