Abstract common code between MVC 5 Controllers and Web Api Controllers - c#

I have an application with an ASP .Net MVC 5 front end and a Web Api 2 service layer and I would like to use dependency injection so the MVC 5 controllers only rely on abstractions for the Web Api 2 ones.
Since the Web Api controllers mostly use this kind of signature:
public IHttpActionResult SomeMethod(){ return Ok(); }
my first thought was that the interface should be:
IHttpActionResult SomeMethod();
Now I have a class library with the interfaces for the services but that means that this class library would need a reference to System.Web.Http in order to use the IHttpActionResult interface in the signatures.
I have two questions:
Fist this feels out right wrong that this library has a reference to System.Web.Http, is there an alternative to this?
If there isn't an alternative, when I try to add the reference I only get an older version of the library which does not have a definition for that interface, where can I get the correct version from?
Thank you.

I would shove the common logic into a common library with 'normal' inputs and outputs. The two transports (MVC and web api) can then call this library

It really depends on what you are trying to achieve - aka how much abstraction you want to introduce.
If you wan't to move all the common business logic into a service for re-use from here, and potentially anywhere then yes you want to get rid of the System.Web.Http references.
Do this by having a clean interface/implimentation that simply return the result of the actions something like this:
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.
*/
I then allow the controllers for both Web & Api control how to use this BaseResponse to er...respond.
So maybe create a BaseController, and BaseApiController:
For example:
public abstract class BaseApiController : ApiController
{
protected HttpResponseMessage HandleResponse(BaseResponse response)
{
return
!response.IsSuccess
? Request.CreateErrorResponse(HttpStatusCode.BadRequest, response.Errors )
: Request.CreateResponse(HttpStatusCode.OK, response);
}
}
And:
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();
}
}
Then in WebApi Controller:
public HttpResponseMessage DoAction(string param1)
{
return HandleResponse(_customerService.DoSomething(new DoActionRequest { Param1 = param1 }));
}
And in the Web Controller
public ActionResult DoAction(ViewModel viewModel)
{
var response = _customerService.DoSomething(new DoActionRequest { Param1 = param1 });
return HandleResponse(response, "Success");
}
In this way all busienss logic is tucked away and resusable, and the ApiController and Controllers can respond in their own unique ways.

Related

ASP.NET when to use IActionResult and when to use IResult?

I am trying to understand what the pros and cons are of IActionResult and IResult as return types and when to use the approopriate one. From what i've gathered IActionResult is just like IResult but with more options on how to handle the result?
IActionResult :: Defines a contract that represents the result of an action method.ASP.NET Core 7
IActionResult allows you to provide some more operations based on your actions like redirecting, changing the response's format etc.
Use IActionResult on the side of your web application - MVC, since it gives you more approaches to handle requests.
IResult :: Defines a contract that represents the result of an HTTP endpoint. ASP.NET Core 7
ASP.NET Core is a new static Results utility class to produce common HTTP responses as IResults. IResult is a new return type that got introduced with Minimal APIs.
IActionResult: Defines a contract that represents the result of an action method.
Example:
public IActionResult OkResult()
{
return Ok();
}
or
public IActionResult NoContentResult()
{
return NoContent();
}
IResult: Defines a contract that represents the result of an HTTP endpoint.
Example:
class CusomtHTMLResult : IResult
{
private readonly string _htmlContent;
public CusomtHTMLResult(string htmlContent)
{
_htmlContent = htmlContent;
}
public async Task ExecuteAsync(HttpContext httpContext)
{
httpContext.Response.ContentType = MediaTypeNames.Text.Html;
httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(_htmlContent);
await httpContext.Response.WriteAsync(_htmlContent);
}
}
(Line: 1) The 'CustomHTMLResult' implementing the
'Microsoft.AspNetCore.Http.IResult'.
(Line: 3-7) Injecting the HTML result.
(Line: 8) The 'ExecuteAsync' method gets automatically executed on
initializing 'CustomHTMLResult' object.
(Line: 10-12) Updating the 'HttpContext' object with our HTML
response, like defining 'ContentType', 'ContentLength'.
static class CustomResultExtensions
{
public static IResult HtmlResponse(this IResultExtensions extensions, string html)
{
return new CusomtHTMLResult(html);
}
}
The 'CustomResultExtions' is a static class. where we can define the extension method of our custom response.

Dotnet core method injection with controller methods

Lets say i have the following controller in dotnet core:
[Route("api/v1/[controller]")]
public class ValuesController : Controller
{
private readonly IHandler<ValuesRequest, ValuesResponse> _valueHandler;
private readonly IHandler<ValuesIdRequest, ValuesIdResponse> _valueIdHandler;
public ValuesController(IHandler<ValuesRequest, ValuesResponse> valueHandler,
IHandler<ValuesIdRequest, ValuesIdResponse> valueIdHandler)
{
_valueHandler = valueHandler;
_valueIdHandler = valueIdHandler;
}
[HttpGet]
public ValuesResponse Get(ValuesRequest request)
{
return _valueHandler.Handle(request);
}
[HttpGet("{id}")]
public ValuesIdResponse Get(ValuesIdRequest request)
{
return _valueIdHandler.Handle(request);
}
}
As you can see in the code above, I'm using dependency injection though the constructor. However, I was thinking on how I could reduce the amount of code. So, I was thinking about using method injection, which should reduce the code to something like this:
[Route("api/v1/[controller]")]
public class ValuesController : Controller
{
[HttpGet]
public ValuesResponse Get(ValuesRequest request, IHandler<ValuesRequest, ValuesResponse> handler)
{
return handler.Handle(request);
}
[HttpGet("{id}")]
public ValuesIdResponse Get(ValuesIdRequest request, IHandler<ValuesIdRequest, ValuesIdResponse> handler)
{
return handler.Handle(request);
}
}
I was wondering if it is possible to do something like this in combination with controller params. I tried finding an answer on the web, however I could not find similar problem/solution.
Reference Action Injection with FromServices
Sometimes you don't need a service for more than one action within your controller. In this case, it may make sense to inject the service as a parameter to the action method. This is done by marking the parameter with the attribute [FromServices] as shown here:
public ValuesResponse Get(ValuesRequest request, [FromServices]IHandler<ValuesRequest, ValuesResponse> handler)
{
return handler.Handle(request);
}
While the answer would work using [FromService] within your actions, I have another suggestion.
From what I understand by reading the code you have provided is, that you use some kind of CQRS. For that case I can suggest MediatR. You will then only need to inject one interface into your controller and send your request using the IMediator. This way you will keep your controller small and clean and you will not need to inject all the other handlers.
There is a nice and handy extension for Microsoft's IoC-Container to register all your handlers and all other necessary classes to use MediatR.
services.AddMediatR(typeof(Startup).Assembly);

Should same methods from different controllers be moved to a CommonController?

I have two controllers that have few same methods:
public class Controller1 : Controller
{
private readonly ITestBL bl;
public Controller1(ITestBL bl)
{
this.bl= bl;
}
[HttpGet]
public ActionResult Method1(string data)
{
using (bl)
{
var res = ...
return Json(res, JsonRequestBehavior.AllowGet);
}
}
[HttpGet]
public ActionResult Method2(string data, int data2)
{
using (bl)
{
var res = ...
return Json(res, JsonRequestBehavior.AllowGet);
}
}
// other methods
}
And the second controller also has those two methods.
Should I create some common controller to keep those methods? So, it will look like this:
public abstract class CommonController: Controller
{
private readonly ITestBL bl;
protected Controller1(ITestBL bl)
{
this.bl= bl;
}
[HttpGet]
public ActionResult Method1(string data)
{
using (bl)
{
var res = ...
return Json(res, JsonRequestBehavior.AllowGet);
}
}
[HttpGet]
public ActionResult Method2(string data, int data2)
{
using (bl)
{
var res = ...
return Json(res, JsonRequestBehavior.AllowGet);
}
}
}
And my Controller1 and Controller2 will be:
public class Controller1 : CommonController
{
private readonly ITestBL bl;
public Controller1(ITestBL bl)
:base(bl)
{
}
// methods
}
Is that the proper way to do that? Do I miss anything or is there a better way?
Should same methods from different controllers be moved to a CommonController?
Yes and you should not use Inheritance. I'm sure there are plenty of people who may disagree, however your example is extremely generic and gives very poor context there is no good reason all controllers need the same code (Inheritance or not). Your questions context has no reason for it to be the case in the OOP realm of Has A vs Is A (Excerpt below).
A House is a Building (inheritance);
A House has a Room (composition);
What it appears you are doing is neither of these.
If your interface was IVehicleEngine and your controllers were FerarriVehicleController and FordVehicleController now it makes sense in a context. In this case each controller should use inheritance, it makes sense.
In my own humble opinions, inheriting from your own controller can be quite difficult in multiple terms. First, it's not intuitive; that is it will become tribal knowledge because it replaces a normal convention that most programmers adhere to (that is deriving from the base MVC controller). Secondly, I've seen it become the one place that everyone decides to add code to (God Object) even though it may not be applicable from some controllers. Thirdly, it makes it difficult to reuse url's that make sense for the derived type but not the base type (/search?searchFor=). There are a number of other considerations that are very specific to MVC because of it's exposure to the web (security etc etc).
Depending on implementation you may also experience difficulty in determining which URL to use under what circumstances.
Is /Controller1/Method1/Data/1 the same as /Controller2/Method1/Data/1 but different from /Controller3/Method1/Data/1? If they are all the same or some are the same and some are different then there is most likely something wrong with the architecture.
Nothing wrong with inheriting from a base controller. As it adheres to the DRY principle. I would go with :
public abstract class CommonController: Controller
{
protected readonly ITestBL bl;
protected Controller1(ITestBL bl)
{
this.bl= bl;
}
[HttpGet]
public virtual ActionResult Method1(string data)
{
var res = ...
return Json(res, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public virtual ActionResult Method2(string data, int data2)
{
var res = ...
return Json(res, JsonRequestBehavior.AllowGet);
}
}
Main differences being.
I removed "using". Like the others have said it's best to let your DI framework decide when to dispose of the injected class.
Make the action results virtual. The inheriting controllers may have the same requirements now, but there is no guarantee that they will stay that way in the future. So declaring them as virtual allows for future changes in scope/requirements as they can be overridden.
I made the injected class "protected" rather then "private" as other methods in both inheriting controllers may need it too.

Proper use of the Factory Pattern?

I am trying to figure out the best solution for getting error messages in between my service layer and WebApi controllers.
I have a class ModelStateDictionaryWrapper that implements an interface IValidationDictionary
ModelStateDictionaryWrapper
public class ModelStateDictionaryWrapper : IValidationDictionary
{
private readonly ModelStateDictionary modelStateDictionary;
public bool IsValid
{
get
{
return this.modelStateDictionary.IsValid;
}
}
public ModelStateDictionaryWrapper(ModelStateDictionary modelStateDictionary)
{
Enforce.ArgumentNotNull(modelStateDictionary, "modelStateDictionary");
this.modelStateDictionary = modelStateDictionary;
}
public void AddError(string key, string message)
{
this.modelStateDictionary.AddModelError(key, message);
}
}
IValidationDictionary
public interface IValidationDictionary
{
bool IsValid { get; }
void AddError(string key, string message);
}
In my api controller, I am doing this:
public class CategoryController : ControllerBase<ICategoryService>
{
private ICategoryService categoryService;
public CategoryController(ICategoryService categoryService)
{
this.categoryService = categoryService;
this.categoryService.ValidationDictionary =
new ModelStateDictionaryWrapper(this.ModelState);
}
public IEnumerable<CategoryViewModel> Get()
{
return Mapper.Map<CategoryViewModel[]>(this.Service.GetCategories());
}
}
The problem I have with this is I am making a new ModelStateDictionaryWrapper in the constructor of the service and I dont like that.
So I was thinking of changing this to take a factory like so:
public interface IModelStateWrapperFactory
{
IValidationDictionary GetModelStateWrapper(ModelStateDictionary modelStateDictionary);
}
public class ModelStateWrapperFactory : IModelStateWrapperFactory
{
public IValidationDictionary GetModelStateWrapper(
ModelStateDictionary modelStateDictionary)
{
return new ModelStateDictionaryWrapper(modelStateDictionary);
}
}
And then the api controller would look like this (constructor):
public CategoryController(ICategoryService categoryService,
IModelStateWrapperFactory modelStateWrapperFactory)
{
this.categoryService = categoryService;
this.categoryService.ValidationDictionary =
modelStateWrapperFactory.GetModelStateWrapper(this.ModelState);
}
I think I have removed the tight coupling. Does this look like a good solution?
Yes,
You have broken the dependencies between the classes, so you can mock the services during Unit Testing.
I don't know if you have used data annotations and a validation filter or not yet. If not, I would suggest you use them. More details from here http://www.asp.net/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api
An even better approach would be to completely remove this part out of the controller. It should be moved out of the controller, because:
This is effectively a cross-cutting concern and your controller should not be concerned with it; you are violating the Single Responsibility Principle.
Most (if not all) of your controllers will need this construct, which means that you have to repeat it all over the place, making it easy to forget it at some places; you are violating the Don't Repeat Yourself (DRY) principle.
This construct is only possible in the case that the class that needs validation is directly injected into the controller, which might not always be the case. Sometimes you'll need to do validation deeper down the object graph, or you might want to wrap the service with a decorator or interceptor, rendering this approach useless -or at least- extremely troublesome.
There are several solutions to this approach. The first that comes to my mind is to move the setting of the ModelState up, out of the CategoryController's constructor, for instance:
public IHttpController Create(HttpRequestMessage request,
HttpControllerDescriptor descriptor, Type type)
{
var wrapper = new ModelStateDictionaryWrapper();
var controller = new CategoryController(new CategoryService(wrapper));
wrapper.ModelState = controller.ModelState;
return controller;
}
Another -completely different- approach is to to not use the ModelState property at all, but to let your business layer throw specific validation exceptions and catch them higher up the call stack and transform them to Web API status codes.
Throwing exceptions would be a much better approach for the business layer, since this prevents validation errors to go unnoticed. Besides, a design where you fill a dictionary with validation errors is related to Web API and MVC, and is not something that your business layer should be concerned with.
You can do the following in your controller when your BL throws validation exceptions:
public class CategoryController : ControllerBase<ICategoryService>
{
private ICategoryService categoryService;
public CategoryController(ICategoryService categoryService)
{
this.categoryService = categoryService;
}
public HttpResponseMessage Update(CategoryViewModel model)
{
try
{
this.categoryService.Update(model.Category);
}
catch (ValidationException ex)
{
return WebApiValidationHelper.ToResponseCode(ex);
}
}
}
Downside here is of course that your try-catch statements with the calls to the WebApiValidationHelper.ToResponseCode will be duplicated in all your controllers; you'll be violating DRY.
So what you can do instead is extract this code into an DelegatingHandler. My preference would always be to use decorators, but unfortunately Web API makes it impossible to decorate ApiControllers, due to a quirk in its design. So you can inject the following DelegatingHandler into the Web API pipeline:
public class ValidationDelegationHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
try
{
return await base.SendAsync(request, cancellationToken);
}
catch (ValidationException ex)
{
return WebApiValidationHelper.ToResponseCode(ex);
}
}
}
This handler can be injected as follows:
config.MessageHandlers.Add(new ValidationDelegationHandler());

unit testing dotnetopenauth ctp

I'm implementing an oauth provider using DotNetOpenAuth CTP library. So I have created an mvc3 application, which has an OAuth Controller with 3 methods in it with the purpose of authorizing third party applications. The controller has an IOAuthService which encapsulates all the logic that the library must do to complete certain tasks, however, the service methods return DotNetOpenOAuth objects that have their constructors protected.
I would like to test the behavior of the methods within my OAuthController, for this, I'm trying to mock my service methods but I havent't been able to do this. I have to tell moq library what type of object I'm expecting the service method to return, and since I cannot access constructors of these objects, I'm not able to perform a test over my controller method.
The controller:
public class OAuthController : Controller
{
private readonly IOAuthService _oAuthService;
public OAuthController(IOAuthService oAuthService)
{
_oAuthService = oAuthService;
}
[Authorize, AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult Authorize()
{
ClientApplication requestingClient;
var request = _oAuthService.ReadAuthorizationRequest();
if (request == null)
{
throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request.");
}
var response = _oAuthService.RequestClientAuthorization(GetIdentity().Name, out requestingClient, request);
if (response != null)
{
return response.AsActionResult();
}
var model = new AuthorizeClientApplicationViewModel
{
ClientApplication = requestingClient.Name,
Scope = request.Scope,
AuthorizationRequest = request,
};
return View(model);
}
public virtual IIdentity GetIdentity()
{
return User.Identity;
}
}
I want to test that whenever a third party app has no authorization, a view will pop up to the user asking for his permission to authorize the app. Fot this i need to mock:
_oAuthService.RequestClientAuthorization
The setup of my test method will then look like :
var oAuthService = new Mock<IOAuthService>();
oAuthService.Setup(a => a.RequestClientAuthorization(userName, out client, pendingRequest)).Returns(new OutgoingWebResponse()); // DotNetOpenAuth doesn't allow me to do the **new OutgoingWebResponse**
PD: For this question I only wrote one of the controller methods, but there are 3, and they have similar scenarios.
One possibility is to write a wrapper (the same way ASP.NET MVC abstracts all the HTTP Context specific stuff):
public abstract class OutgoingWebResponseWrapperBase
{
protected OutgoingWebResponseWrapperBase() { }
public abstract ActionResult AsActionResult();
}
and then have a naïve implementation:
public class OutgoingWebResponseWrapper: OutgoingWebResponseWrapperBase
{
private readonly OutgoingWebResponse _response;
public OutgoingWebResponseWrapper(OutgoingWebResponse response)
{
_response = response;
}
public override ActionResult AsActionResult()
{
return _response.AsActionResult();
}
}
Now modify the IOAuthService.RequestClientAuthorization method to return a OutgoingWebResponseWrapperBase instead of OutgoingWebResponse.
Just like that:
public interface IOAuthService
{
...
OutgoingWebResponseWrapperBase RequestClientAuthorization(...);
}
Obviously your controller code will stay absolutely the same. It's just that now you can mock the return type of the RequestClientAuthorization in your unit test because it is an abstract class. You can also mock the AsActionResult abstract method call to return some expected mocked instance and you will assert in your unit test that the controller action that you are testing returned this expected action result.
If the constructor is protected, then a derived type could access it. Can you simply use Moq to create a mock of OutgoingWebResponse (which internally will make Moq derive from it and call the protected constructor I think) and return that from your mock method implementation?
Something like this:
System.Net.HttpWebResponse mockResponse; // get this from somewhere
new Moq.Mock<DotNetOpenAuth.Messaging.OutgoingWebResponse>(mockResponse, 5);
This should let you mock up an OutgoingWebResponse. The next problem becomes, where do you get yoru HttpWebResponse instance, since that too has only a protected constructor. You could continue the chain and mock up that the same what as OutgoingWebResponse, and see how far you get.

Categories

Resources