c# WebApi提供程序类库中的IHttpActionResult

本文关键字:IHttpActionResult 类库 程序 WebApi | 更新日期: 2023-09-27 18:03:23

所以我已经创建了一个提供者,它将处理我所有的代码。最初是这样的:

public class AnswerProvider : ApiController
{
    private readonly IUnitOfWork _unitOfWork;
    private readonly AnswerService _answerService;
    private QuestionService _questionService;
    public QuestionService QuestionService => _questionService ?? (_questionService = new QuestionService(this._unitOfWork));
    public AnswerProvider(IUnitOfWork unitOfWork)
    {
        this._unitOfWork = unitOfWork;
        this._answerService = new AnswerService(unitOfWork);
    }
    public async Task<IHttpActionResult> CreateAsync(AnswerRequestModel model)
    {
        try
        {
            // Validate our answer count
            await ValidateAnswerCountAsync(model.QuestionId);
            // Create our model
            var answer = ModelFactory.Create(model);
            // Add our images to our answer
            answer.Images = model.Images;
            // Save our model
            this._answerService.Create(answer);
            // Save the database changes
            await this._unitOfWork.SaveChangesAsync();
            // Return our updated model
            return Ok(ModelFactory.Create(answer));
            // If there is an error
        }
        catch (Exception ex)
        {
            // Return our error
            return BadRequest(ex.Message.ToString());
        }
    }
    /// <summary>
    /// Validates the answers based on the question type
    /// </summary>
    /// <param name="id">The id of the question</param>
    /// <returns></returns>
    private async Task ValidateAnswerCountAsync(int id)
    {
        // Get our question
        var question = await this.QuestionService.GetAsync(id, "Answers");
        // If we have 3 answers or more
        if (question.Answers.Count >= 3 && question.Type == QuestionType.Boolean)
        {
            // Throw an error
            throw new InvalidOperationException("A Boolean question can only have 3 answers");
        }
    }
}
我继承了ApiController,因为我想获得访问OkBadRequest和其他这样的方法,这是唯一的原因。当我尝试运行这段代码时,即使它已经编译了,我也会得到这个错误:

HttpControllerContext。配置不能为空

我认为这是因为我试图继承ApiController,我不应该这样做。是否有另一种方式,我可以获得访问Ok和其他类似的方法,而不继承ApiController。请记住,我将有不止一个供应商。

c# WebApi提供程序类库中的IHttpActionResult

不要从ApiController继承,因为它是由请求管道中的工厂实例化的。您应该仅为实际的api控制器实例继承它,而不是为了方便某些现有方法。最好的解决方案是在您的提供商/服务/任何中抛出自定义异常,并在控制器中捕获它们,并返回正确的HttpStatus或让异常通过,这将导致500状态。

根据要求,虽然我已经创建了一个小包装围绕ApiController,你可以重用在你的提供者/服务/等基于一个接口(所以它很容易抽象和易于测试)。

// demo of controller calling your Provider
public class SomeController : ApiController
{
    public async Task<IHttpActionResult> Get()
    {
        var wrapper = this.ActionWrapper();
        var answerProvider = new AnswerProvider(wrapper);
        var result = await answerProvider.CreateAsync(model);
    }
}
// a simple extension on the ApiController
public static class WrapperExtension
{
    public static IActionWrapper ActionWrapper(this ApiController controller)
    {
        return new ApiActionWrapperContext(controller);
    }
}
// wrapped in interface so its easy to unit test the Provider
public interface IActionWrapper
{
    OkResult Ok();
    BadRequestResult BadRequest();
    BadRequestErrorMessageResult BadRequest(string message);
    OkNegotiatedContentResult<T> Ok<T>(T content);
}
// the implementation, this takes the current Controller and uses it as the context to return the same result types
// only implemented Ok and BadRequest as a demo, you can extend it as needed
public class ApiActionWrapperContext : IActionWrapper
{
    private ApiController _controller;
    public ApiActionWrapperContext(ApiController controller)
    {
        _controller = controller;
    }
    public BadRequestResult BadRequest()
    {
        return new BadRequestResult(_controller);
    }
    public BadRequestErrorMessageResult BadRequest(string message)
    {
        return new BadRequestErrorMessageResult(message, _controller);
    }
    public OkResult Ok()
    {
        return new OkResult(_controller);
    }
    public OkNegotiatedContentResult<T> Ok<T>(T content)
    {
        return new OkNegotiatedContentResult<T>(content, _controller);
    }
}
// provider shortered with just some relevant code to demo
// notice constructor, the new private field, and the use of it
public class AnswerProvider
{
    private IActionWrapper _actionWrapper;
    public AnswerProvider(IActionWrapper actionWrapper)
    {
        if(actionWrapper == null)
            throw new ArgumentNullException("actionWrapper");
        _actionWrapper = actionWrapper;
    }
    public async Task<IHttpActionResult> CreateAsync(AnswerRequestModel model)
    {
        try
        {
            // Validate our answer count
            await ValidateAnswerCountAsync(model.QuestionId);
            // Create our model
            var answer = ModelFactory.Create(model);
            // Add our images to our answer
            answer.Images = model.Images;
            // Save our model
            this._answerService.Create(answer);
            // Save the database changes
            await this._unitOfWork.SaveChangesAsync();
            // Return our updated model
            return this._actionWrapper.Ok(ModelFactory.Create(answer));
            // If there is an error
        }
        catch (Exception ex)
        {
            // Return our error
            return this._actionWrapper.BadRequest(ex.Message.ToString());
        }
    }
}
相关文章:
  • 没有找到相关文章