MVC 5控制器和Web Api控制器之间的抽象公共代码

时间:2015-03-05 21:20:38

标签: c# asp.net-mvc-5 asp.net-web-api2

我有一个ASP .Net MVC 5前端和Web Api 2服务层的应用程序,我想使用依赖注入,因此MVC 5控制器只依赖于Web Api 2的抽象。

由于Web Api控制器大多使用这种签名:

public IHttpActionResult SomeMethod(){ return Ok(); }

我的第一个想法是界面应该是:

IHttpActionResult SomeMethod();

现在我有一个带有服务接口的类库,但这意味着这个类库需要引用System.Web.Http才能在签名中使用IHttpActionResult接口。

我有两个问题:

  1. 首先感觉这个库有一个对System.Web.Http的引用是错误的,有替代方法吗?
  2. 如果没有替代方案,当我尝试添加引用时,我只会获得该库的旧版本,该版本没有该接口的定义,我在哪里可以获得正确的版本?
  3. 谢谢。

2 个答案:

答案 0 :(得分:1)

我会将常用逻辑推入具有“正常”输入和输出的公共库中。然后两个传输(MVC和web api)可以调用此库

答案 1 :(得分:1)

这实际上取决于你想要实现的目标 - 也就是你要引入多少抽象。

如果您不想将所有常见业务逻辑移动到服务中以便从此处重复使用,并且可能在任何地方,那么您希望摆脱System.Web.Http引用。

通过使用干净的界面/ implimentation来简单地返回这样的操作结果:

public interface ICustomerService 
{
    BaseResponse DoSomething(BaseRequest request);
}

public abstract class BaseResponse 
{
    public bool IsSuccess { get; set; }
    public IList<string> Errors { get; set; }
}

/*
Note: BaseResponse & BaseRequest, follow the command pattern for passing information you would impliment concrete versions of these.
*/

然后我允许控制器用于Web和&amp; Api控制如何使用此BaseResponse来响应...

因此,可以创建一个BaseControllerBaseApiController

例如:

public abstract class BaseApiController : ApiController 
{
        protected HttpResponseMessage HandleResponse(BaseResponse response)
        {
            return
                !response.IsSuccess
                    ? Request.CreateErrorResponse(HttpStatusCode.BadRequest, response.Errors )
                    : Request.CreateResponse(HttpStatusCode.OK, response);
        }
}

public abstract class BaseController : Controller
{
    protected ActionResult HandleResponse(BaseResponse response, string redirectToAction)
    {
        if (response.IsSuccess) 
            return RedirectToAction(redirectToAction);

        foreach (var error in response.Errors)
        {
            ModelState.AddModelError(string.Empty, error);
        }

        return View();
    }
}

然后在WebApi Controller:

public HttpResponseMessage DoAction(string param1)
    {
        return HandleResponse(_customerService.DoSomething(new DoActionRequest { Param1 = param1 }));
    }

并在Web控制器中

public ActionResult DoAction(ViewModel viewModel)
    {
        var response = _customerService.DoSomething(new DoActionRequest { Param1 = param1 });

        return HandleResponse(response, "Success");
    }

通过这种方式,所有业务逻辑都隐藏起来并可重复使用,ApiController和控制器可以以自己独特的方式响应。