Removing boilerplate from ASP.NET MVC actions - c#

I have something like this in almost every action:
public ActionResult Show(int object_id)
{
Object obj = ObjectRepository.ById(object_id);
if (obj == null)
{
throw new HttpException(404);
}
if (obj.SomeCheck)
{
throw new HttpException(403);
}
// processing
}
Question is how to move object getting (and throwing http exceptions) away from action and have something like this:
public ActionResult Show(Object obj)
{
// processing
}
UPD: Can't change ObjectRepository and model itself, it's used not only with ASP.NET but in other parts of the project.

One option is to refactor your boilerplate into a private method:
private object GetItem(object obj) {
Object obj = ObjectRepository.ById(object_id);
if (obj == null) {
throw new HttpException(404);
}
if (obj.SomeCheck()) {
throw new HttpException(403);
}
return obj;
}
Then:
public ActionResult Show(int object_id) {
object obj = GetItem(object_id);
// processing
}

As others have suggested you could write filters or invoke an AOP framework like PostSharp.
However, that might be a tall order for some. You might want to consider writing something simple, maintainable and fairly readable, that everyone on the team can immediately understand:
public ActionResult Show(int object_id)
{
SomeClass obj = Require<SomeClass>(object_id, assumption: o => o.SomeCheck);
// processing
}
//Perhaps: put this in a base controller or other common class
private object Require<T>(int id, Func<object, bool> assumption) where T : class
{
var o = ObjectRepository.ById(object_id) as T;
//Result is required
if (o == null) {
throw new HttpException(404);
}
//Verify assumption
if (!assumption(o)) {
throw new HttpException(403);
}
return o;
}

You might look at
Writing a custom filter attribute such as an AuthorizationAttribute or ValidateInputAttribute. They can be applied to the entire controller or to specify methods (actions). See http://msdn.microsoft.com/en-us/magazine/dd695917.aspx#id0070026 for an overview.
You might want to look at using PostSharp (Aspect-Oriented Programming framework) to inject suitable aspects into your methods.

Others have provided some good answers. Among them, I like the idea of using an action filter but unfortunately I don't believe it will work very well as you'll be forced to use property injection (or explicit instantiation - yuck!) for the repository, which I'd prefer to avoid. For this reason, I think a dedicated controller method is a better option.
I will throw one more idea in the hat, though.
You mentioned that you can't change ObjectRepository but you can always abstract it:
public class HttpObjectService /*: IObjectService */
{
private readonly /*I*/ObjectRepository _repository;
public HttpObjectService(/*I*/ObjectRepository repository)
{
if (repository == null) throw new ArgumentNullException("repository");
_repository = repository;
}
public Object ById(int id)
{
var obj = _repository.ById(id);
/* Check and throw HttpExceptions */
}
}
Then inject this into your controller. Whether or not you like the idea of a "web-specific" service that throws HttpExceptionsdirectly is a matter of taste but it is extremely reusable and, in this case, I believe it provides a cleaner separation of concerns than private validation methods in the controller.
The downside, of course, is that you're allowing your controller to delegate its responses (in the event of an error) directly to a third party. You may prefer your controller to have absolute control over this - that would be a reasonable criticism. In that case, you could always pass an ObjectValidator object into the constructor from the controller, which takes care of the validation. This would let your controller maintain control of what exceptions are thrown regardless of the service implementation.
You would have to be considerate of where this fits into your project architecture - it would probably belong in a separate assembly to your MVC project but one that is dedicated to web-based UIs.

Related

Unit Testing a controller that uses windows authentication

-------Please see updates below as I now have this set up for dependency injection and the use of the MOQ mocking framework. I'd still like to split up my repository so it doesn't directly depend on pulling the windowsUser within the same function.
I have a Web API in an intranet site that populates a dropdown. The query behind the dropdown takes the windows username as a parameter to return the list.
I realize I don't have all of this set up correctly because I'm not able to unit test it. I need to know how this "should" be set up to allow unit testing and then what the unit tests should look like.
Additional info: this is an ASP.NET MVC 5 application.
INTERFACE
public interface ITestRepository
{
HttpResponseMessage DropDownList();
}
REPOSITORY
public class ExampleRepository : IExampleRepository
{
//Accessing the data through Entity Framework
private MyDatabaseEntities db = new MyDatabaseEntities();
public HttpResponseMessage DropDownList()
{
//Get the current windows user
string windowsUser = HttpContext.Current.User.Identity.Name;
//Pass the parameter to a procedure running a select query
var sourceQuery = (from p in db.spDropDownList(windowsUser)
select p).ToList();
string result = JsonConvert.SerializeObject(sourceQuery);
var response = new HttpResponseMessage();
response.Content = new StringContent(result, System.Text.Encoding.Unicode, "application/json");
return response;
}
}
CONTROLLER
public class ExampleController : ApiController
{
private IExampleRepository _exampleRepository;
public ExampleController()
{
_exampleRepository = new ExampleRepository();
}
[HttpGet]
public HttpResponseMessage DropDownList()
{
try
{
return _exampleRepository.DropDownList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
UPDATE 1
I have updated my Controller based on BartoszKP's suggestion to show dependency injection.
UPDATED CONTROLLER
public class ExampleController : ApiController
{
private IExampleRepository _exampleRepository;
//Dependency Injection
public ExampleController(IExampleRepository exampleRepository)
{
_exampleRepository = exampleRepository;
}
[HttpGet]
public HttpResponseMessage DropDownList()
{
try
{
return _exampleRepository.DropDownList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
UPDATE 2
I have decided to use MOQ as a mocking framework for unit testing. I'm able to test something simple, like the following. This would test a simple method that doesn't take any parameters and doesn't include the windowsUser part.
[TestMethod]
public void ExampleOfAnotherTest()
{
//Arrange
var mockRepository = new Mock<IExampleRepository>();
mockRepository
.Setup(x => x.DropDownList())
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
ExampleController controller = new ExampleController(mockRepository.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
//Act
var response = controller.DropDownList();
//Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
I need help testing the DropDownList method (one that does include code to get the windowsUser). I need advice on how to break this method apart. I know both parts shouldn't been in the same method. I don't know how to arrange splitting out the windowsUser variable. I realize this really should be brought in as a parameter, but I can't figure out how.
You usually do not unit-test repositories (integration tests verify if they really persist the data in the database correctly) - see for example this article on MSDN:
Typically, it is difficult to unit test the repositories themselves, so it is often better to write integration tests for them.
So, let's focus on testing only the controller.
Change the controller to take IExampleRepository in its constructor as a parameter:
private IExampleRepository _exampleRepository;
public ExampleController(IExampleRepository exampleRepository)
{
_exampleRepository = exampleRepository;
}
Then, in your unit tests, use one of mocking frameworks (such as RhinoMock for example) to create a stub for the sole purpose of testing the controller.
[TestFixture]
public class ExampleTestFixture
{
private IExampleRepository CreateRepositoryStub(fake data)
{
var exampleRepositoryStub = ...; // create the stub with a mocking framework
// make the stub return given fake data
return exampleRepositoryStub;
}
[Test]
public void GivenX_WhenDropDownListIsRequested_ReturnsY()
{
// Arrange
var exampleRepositoryStub = CreateRepositoryStub(X);
var exampleController = new ExampleController(exampleRepositoryStub);
// Act
var result = exampleController.DropDownList();
// Assert
Assert.That(result, Is.Equal(Y));
}
}
This is just a quick&dirty example - CreateRepositoryStub method should be of course extracted to some test utility class. Perhaps it should return a fluent interface to make the test's Arrange section more readable on what is given. Something more like:
// Arrange
var exampleController
= GivenAController()
.WithFakeData(X);
(with better names that reflect your business logic of course).
In case of ASP.NET MVC, the framework needs to know how to construct the controller. Fortunately, ASP.NET supports the Dependency Injection paradigm and a parameterless constructor is not required when using MVC unity.
Also, note the comment by Richard Szalay:
You shouldn't use HttpContext.Current in WebApi - you can use base.User which comes from HttpRequestBase.User and is mockable. If you really want to continue using HttpContext.Current, take a look at Mock HttpContext.Current in Test Init Method
One trick that I find very useful when trying to make old code testable when said code is accessing some global static or other messy stuff that I can't easily just parameterize is to wrap access to the resource in a virtual method call. Then you can subclass your system under test and use that in the unit test instead.
Example, using a hard dependency in the System.Random class
public class Untestable
{
public int CalculateSomethingRandom()
{
return new Random().Next() + new Random().Next();
}
}
Now we replace var rng = new Random();
public class Untestable
{
public int CalculateSomethingRandom()
{
return GetRandomNumber() + GetRandomNumber();
}
protected virtual int GetRandomNumber()
{
return new Random().Next();
}
}
Now we can create a testable version of the class:
public class Testable : Untestable
{
protected override int GetRandomNumber()
{
// You can return whatever you want for your test here,
// it depends on what type of behaviour you are faking.
// You can easily inject values here via a constructor or
// some public field in the subclass. You can also add
// counters for times method was called, save the args etc.
return 4;
}
}
The drawback with this method is that you can't use (most) isolation frameworks to implement protected methods (easily), and for good reason, since protected methods are sort of internal and shouldn't be all that important to your unit tests. It's still a really handy way of getting things covered with tests so you can refactor them, instead of having to spend 10 hours without tests, trying to do major architectual changes to your code before you get to "safety".
Just another tool to keep in mind, I find it comes in handy from time to time!
EDIT: More concretely, in your case you might want to create a protected virtual string GetLoggedInUserName(). This will technically speaking keep the actual call to HttpContext.Current.User.Identity.Name untested, but you will have isolated it to the simplest smallest possible method, so you can test that the code is calling the correct method the right amount of times with the correct args, and then you simply have to know that HttpContext.Current.User.Identity.Name contains what you want. This can later be refactored into some sort of user manager or logged in user provider, you'll see what suits best as you go along.

C# Extension methods and protection level?

I am trying to write an extension method for the MVC controller class, since I see such code repeatedly in my program:
if (viewModel == null)
{
return HttpNotFound();
}
return View(viewModel);
The idea is that I want an extension method called ViewModelResult() to take care of this, so that it will return either an ActionResult or HttpNotFound result depending on whether the view model is available. This way, I dont have to write these 3-4 lines of code every time.
However, it seems that the protection level of the methods View() and HttpNotFound() in the MVC controller is causing some serious trouble. I've written the code as below but it will not work:
public static class ExtensionController
{
public static ActionResult ViewModelResult(this Controller controller, ViewModel viewModel)
{
if (viewModel == null)
{
return controller.HttpNotFound();
}
return controller.View(viewModel);
}
}
It throws error messages such as "System.Web.MVC.Controller.View() is inaccessible due to its protection level". This confuses me, I thought in extension methods all private and protected methods of the very object labeled by this keyword are accessible, just like when you write a method in this class. But I've been proved wrong, those non-public methods are inaccessible in extension methods.
Now the question is, how can I get by this issue? I am kinda clueless, don't know what I can do about this. The MVC controller class comes within the .NET framework, and I cannot modify the source code. It is not recommended to change internal implementation of .NET framework anyway. Can anyone help? What do you recommend me to do in this case?
You can create a subclass of the Controller class and add methods to that.
public abstract class ControllerBase : Controller
{
protected ActionResult ViewModelResult(ViewModel viewModel)
{
if (viewModel == null)
{
return HttpNotFound();
}
return View(viewModel);
}
}
public class ValuesController : ControllerBase
{
public ActionResult Index()
{
var vm = ...;
return ViewModelResult(vm);
}
}
Just to complete the answer of #Markus:
You can access the View method only by inheritance as you can see on the MSDN Controller.View Method
Extension methods are purely syntactic sugar and are replaced at compile time by your ExtensionController.ViewModelResult(this,viewModel);
Hence you can access only public modifiers if your extension class is not part of the library of the object you want to extend.

Removing Convert.ToDecimal Dependency (Dependency Injection)

I am currently learning dependency injection to create more maintainable code with MVC. I am already injecting a model and a calculator service to my controller instead of having a to new up dependency.
I have a few Convert.ToDecimal calls in my constructor, and didn't know if I needed to worry about using dependency injection to remove the static method call which is a DI design smell. Is removing that going too far?
private readonly ICalculationService _calculation;
private readonly ICalculatorModelService _calculatormodel;
public CalculatorController(ICalculationService calculation,
ICalculatorModelService calculatormodel) {
_calculation = calculation;
_calculatormodel = calculatormodel;
}
public ActionResult Index() {
var model = _calculatormodel;
return View(model);
}
public PartialViewResult Calculate(string submit, string txtValue,
string value1) {
var model = _calculatormodel;
if (submit == "+")
{
if (Session["value1"] == null)
Session.Add("value1",Convert.ToDecimal(txtValue));
else
Session["value1"] = value1;
}
else if (submit == "=")
{
if (Session["value1"] == null)
Session.Add("value1", 0);
model.Result = _calculation.Calculate(Convert
.ToDecimal(Session["value1"]), Convert.ToDecimal(txtValue));
}
return PartialView("_Calculator", model);
}
If I understand the question, you are worried about the static call of Convert and you ask if this class should also be injected.
If that's the case, you don't have too. Same goes for similar static calls like Math. methods etc.
The rule I follow for such .NET helper calls is, if the call is deterministic, i.e. always returning same output for the same input, then go ahead call it (anyway you depend on .NET framework, right?). But if the call is non deterministic, like Datetime.Now or use of Random class, then I inject these dependencies (which makes code more testable, of course)

How can I add common postprocessing applied after customization

I have defined ISpecimenBuilder for my models and use it like that:
new Fixture().Customize(new ModelCustomization());
I want to use it in most of my tests concerning model. I also want to apply some form of post-processing in one of my test classes. Specifically I want to fill property CompanyHistory of all created Offers. It feels like it could be done like that:
fixture.Build<Offer>()
.With(o => o.CompanyHistory, _previouslyCreatedCompanyHistory)
.Create();
But Build<T> disables all customizations and I need them.
Can I do something like that?
fixture.Build<Offer>()
.WithCustomization(new ModelCustomization()) // there is no such method, but i'd like it to be
.With(o => o.CompanyHistory, _previouslyCreatedCompanyHistory)
.Create();
Or should I write my own Behavior? If so, can someone provide me with guidelines on doing that?
EDIT:
I feel I have to stress out that I want to use both my common customization (ModelCustomization) and Postprocessor
EDIT 2:
What I meant from the beginning is that ModelCustomization can (and should) create Offer and my to-be postprocessor should use that already created specimen and fill some of its properties.
Here is how you can create and use a Postprocessor in this case:
[Fact]
public void Test()
{
var fixture = new Fixture();
// (You may also include other customizations here.)
fixture.Customizations.Add(
new FilteringSpecimenBuilder(
new Postprocessor(
new MethodInvoker(
new ModestConstructorQuery()),
new OfferFiller()),
new OfferSpecification()));
var offer = fixture.Create<Offer>();
// -> offer.CompanyHistory has the value supplied in OfferFiller command.
}
The OfferFiller command is defined as:
internal class OfferFiller : ISpecimenCommand
{
public void Execute(object specimen, ISpecimenContext context)
{
if (specimen == null)
throw new ArgumentNullException("specimen");
if (context == null)
throw new ArgumentNullException("context");
var offer = specimen as Offer;
if (offer == null)
throw new ArgumentException(
"The specimen must be an instance of Offer.",
"specimen");
Array.ForEach(offer.GetType().GetProperties(), x =>
{
if (x.Name == "CompanyHistory ")
x.SetValue(offer, /*value*/);
else
x.SetValue(offer, context.Resolve(x.PropertyType));
});
}
}
The OfferSpecification is defined as:
internal class OfferSpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
var requestType = request as Type;
if (requestType == null)
return false;
return typeof(Offer).IsAssignableFrom(requestType);
}
}
I had a similar problem and have tried solutions mentioned here, but they didn't work as expected. Finally, I've found an implementation of a PostProcessWhereIsACustomization class, that does exactly what I needed:
AutoFixture customization to allow insertion of arbitrary postprocessing logic a la Customize( c=>c.Do()) but in a global manner Revised for v3 (initally for v2)
May save somebody some Googling.
I ended up writing following Customization:
private class OfferWithCompanyModelCustomization: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new FilteringSpecimenBuilder(new Postprocessor(
new ModelSpecimenBuilder(), new FillModelPropertiesCommand()), new ExactTypeSpecification(typeof(Offer))));
}
private class FillModelPropertiesCommand : ISpecimenCommand
{
public void Execute(object specimen, ISpecimenContext context)
{
var offer = specimen as Offer;
offer.CompanyHistory = (CompanyHistory)context.Resolve(typeof(CompanyHistory));
}
}
}
This works, but it's far from perfect. As you can see, I refer to ModelSpecimenBuilder directly, so I'm dependent on implementation (as postprocessor I'd like not to be).
Answer posted by #Nikos is not satisfying, because his customization ignores previous customizations in chain of responsibility.
When we invoke the Create method, a CompositeSpecimenBuilder will invoke the Create method of all its contained builders until one of them provides a specimen. At this point the request is considered to be satisfied, and the rest of the builders are ignored.
source: AutoFixture Documentation

How can I pass service layer validation messages back to the caller?

I've done alot of research, including here on SO, and I can't seem to find clear direction. I currently have an ASP.NET MVC3 application, with a service layer that sits on top of a repository.
In my service layer, I have functions such as:
public class MyService{
public void CreateDebitRequest(int userId, int cardId, decimal Amount, .... )
{
//perform some sort of validation on parameters, save to database
}
public void CreateCreditRequest(.....)
}
//perform some sort of validation on parameters, save to database
}
public void CreateBatchFile()
{
//construct a file using a semi-complex process which could fail
//write the file to the server, which could fail
}
public PaymentTransaction ChargePaymentCard(int paymentCardId, decimal amount)
{
//validate customer is eligible for amount, call 3rd party payments api call,
//...save to database, other potential failures, etc.
}
}
I've seen people say that parameter validation isn't very exceptional, and so throwing an exception is not very fitting. I also don't love the idea of passing in an out paramater, such as a string, and checking for an empty value. I've considered implementing a ValidationDictionary class, and making it a property of any given service class (it would contain an IsValid boolean, and a List of error messages, and could be checked after any given function call in the service layer to see how things went). I could check the ValidationDictionary status after running any given function:
var svc = new MyService();
svc.CreateBatchFile();
if (svc.ValidationDictionary.IsValid)
//proceed
else
//display values from svc.ValidationDictionary.Messages...
The thing I don't like about this is that I would have to update it for every service layer function call, to avoid having it retain old values (if I chose not to use it for many or most functions, one would still expect it to have a meaningful or null value after running any given function). Another thing I've considered is passing in the ValidationDictionary for each function call that might have detailed validation information, but then I am back to using an out parameter...
Do any of you have recommendations? I can't seem to figure out any clean way of doing this. Sometimes returning null for a function is enough information, but sometimes I'd like a little more validation information passed back to the caller. Any advice would be appreciated!
Edit to clarify:
My service layer is not aware that it is an MVC application that is consuming it. The service layer just has certain public functions such as CreateBatchFile() or AddDebitRequest(). Sometimes returning null is enough for the consumer (in this case a controller, but could be something else) to know what happened, and sometimes the consumer would like some more information from the service layer (maybe to pass along to ModelState if the consumer is a controller). How do I bubble this up from the service layer itself?
This is what I do. Have a class for your validation, and instead of passing parameters pass a view model. So in your case something like this, where ValidationResult is just a simple class w/ MemberName and ErrorMessage properties:
public class DebitRequestValidator{
public IEnumerable<ValidationResult> Validate(DebitRequestModel model){
//do some validation
yield return new ValidationResult {
MemberName = "cardId",
ErrorMessage = "Invalid CardId."
}
}
}
Then create a controller extension method to copy these validation results to the model state.
public static class ControllerExtensions
{
public static void AddModelErrors(this ModelStateDictionary modelState, IEnumerable<ValidationResult> validationResults)
{
if (validationResults == null) return;
foreach (var validationResult in validationResults)
{
modelState.AddModelError(validationResult.MemberName, validationResult.ErrorMessage);
}
}
}
Then in your controller do something like
[HttpPost]
public ActionResult DebitRequest(DebitRequestModel model) {
var validator = new DebitRequestValidator();
var results = validator.Validate(model);
ModelState.AddModelErrors(results);
if (!ModelState.IsValid)
return View(model)
//else do other stuff here
}
Then in your view you can display errors like normal.
#Html.ValidationMessageFor(m => m.CardId)
I used a system where it was passing an array of messages (or collection of classes), each element had codes, descriptions, friendly messages. We used to simply check if anything was there. It worked great between UI and another "service" layer, all exception were caught nicely, they were translated into these validation rules...just an idea
Use ViewModel objects that are passed between the Views and the Controller action methods. The ViewModel objects can handle Validation by a Validate(ValidationDictionary validationDictionary) method.
The controller will have to call the Validate method on ViewModel object before calling any method in the service layer. This should only be necessary for http POST actions.
Your views will then have to display validation messages.
This solution requires that the viewmodel objects are passed between the controller action and the view, but nowadays that is mostly handled by the ModelBinder in MVC.
Your controller (http post) actions will look something like this:
[HttpPost]
public ActionResult Foo(BarViewModel viewModel)
{
viewModel.Validate(ValidationDictionary);
if (!ModelState.IsValid)
{
return View(viewModel);
}
// Calls to servicelayer
}
Your Validate method in your ViewModel will look like this:
public void Validate(ValidationDictionary validationDictionary)
{
if (SomeProperty.Length > 30)
{
validationDictionary.AddError("SomeProperty", "Max length is 30 chars");
}
}
If you're just doing ViewModel Validation, FluentValidation is an excellent library.
If you're wanting to include business validation as feedback to the user, you could use the adapter pattern, it'll give you what you want.
Create an interface (IValidationDictionary or something similar). This interface would define an AddError method and would be passed to your service in order to add error messages.
public interface IValidationDictionary
{
void AddError(string key, string errorMessage);
}
Create a ModelStateAdapter for your mvc application.
public class ModelStateAdapter : IValidationDictionary
{
private ModelStateDictionary _modelState;
public ModelStateAdapter(ModelStateDictionary modelState)
{
_modelState = modelState;
}
public void AddError(string key, string errorMessage)
{
_modelState.AddModelError(key, errorMessage);
}
}
Your service calls that need validation would require the IValidationDictionary
public class MyService
{
public void CreateDebitRequest(int userId, int cardId, decimal Amount, .... , IValidationDictionary validationDictionary)
{
if(userId == 0)
validationDictionary.AddError("UserId", "UserId cannot be 0");
}
}
You would then have a dependency on IValidationDictionary but not on MVC which would also make your solution testable.
If you needed to implement the services in an app that didn't have a ModelStateDictionary, you would just implement the IValidationDictionary interface on a class used for holding your errors.
Controller example:
public ActionResult Test(ViewModel viewModel)
{
var modelStateAdapter = new ModelStateAdapter(ModelState);
_serviceName.CreateDebitRequest(viewModel.UserId, viewModel.CardId, ... , modelStateAdapter);
if(ModelState.IsValid)
return View("Success")
return View(viewModel);
}
Pro's of this approach:
No dependency on the calling libraries
It's possible to mock the IValidationDictionary for tests.
Con's of this approach:
You need to pass IValidationDictionary to every method that you want to do validation on that's going to be returned to the user.
Or
you need to initialise the service's validation dictionary (if you decide to have IValidationDictionary as a private field), in each controller action you want to validate against.

Categories