Different types for Get(id) vs GetAll() - asp.net-web-api

I am creating a very simple web api that allows me to search for things:
public IEnumerable<Thing> GetAllThings()
{
// get all the things!
}
My application has to be able to retrieve a single Thing:
public Thing GetThing(string id)
{
// get a single thing
}
I need more details when retrieving a single Thing than I do when I retrieve all Things. Should I have a separate controller that returns a ThingWithDetails instead of having separate models on GetAllThings and GetThing?

No. You do not have to make a separate controller for ThingsWithDetails. Just have a different overload method. All the below methods will be called based on the request
The below method will be called when you are using url: api/{controller}
public IEnumerable<Thing> GetAllThings()
{
// get all the things!
}
The below method will be called when you are using url: api/{controller}/1
public Thing GetThing(string id)
{
// get a single thing
}
The below method will be called when you are using url: api/{controller}?id=1&name=xyz
public Thing GetThing(string id, string name)
{
// get a single thing
}

As a best practice, you should have a Thing entity with all the possible properties, so you keep the code consistent, and by default you load all of them (assuming that they come from DB).
If you then want to "hide" some properties, you can set them to null just before returning them, using an extension method.
public class Thing
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
public string PropertyC { get; set; }
}
// extension methods
public static class ThingExtensionMethods
{
public static void ToBasicDetails(this Thing thing)
{
// hide properties
thing.PropertyB = null;
thing.PropertyC = null;
}
}
public IEnumerable<Thing> GetAllThings()
{
var things = _db.Things.ToList();
foreach(var item in things)
{
item.ToBasicDetails();
}
return things;
}
public Thing GetThing(string id)
{
var thing = _db.Things.Find(id);
return thing;
}

Defining separate "Thing" and "ThingWithDetails" models makes sense, because you are returning different resource types to the client. The return type defines the response body, so use different models for different response formats.
You don't need to put those methods into separate controllers - it's valid to have an action that returns a ThingWithDetails and another action that returns IEnumerable. It comes down to preference. (I'd probably leave them in the same controller, because they are dealing with the same DB entity.)
This tutorial shows an example.

Related

webapi action overload

here are my actions
public AddressModel[] Get()
{
return addresses.ToArray();
}
public AddressModel Get([FromUri]GetAddressModelById model)
{
return Addresses.FirstOrDefault(x => x.Id == model.Id);
}
...
public class GetAddressModelById
{
public Guid Id { get; set; }
}
the urls looks like this
domain:port/api/controller
domain:port/api/controller/[guid]
and the routing is the default routing.
When I run this i get the exception Multiple actions were found that match the request. what am I missing for this to work?
Try domain:port/api/controller/model=[guid]
It would also be good if you could do:
public AddressModel Get([FromUri]Guid model)
{
...
}
The reason you're getting this error is because if you request for domain:port/api/controller, we cannot decide whether to dispatch it to Get() or Get([FromUri]GetAddressModelById model) with model set to null. You have following two options in this case
Use plain Guid type parameter instead of the class wrapper
Post your complex type in body instead of sending it through URI

View and Domain model, where to perform calculation

I just started using View & Domain model design in my MVC web app but got the question where to perform calculations and other View related actions. I will try to give example below.
My Domain Model (Linq2Sql)
public class Product
{
public int Id;
public string Name;
}
The View Model with new UserCount property which I would like to calculate.
public class ProductViewModel
{
public int Id;
public string Name;
public int UserCount;
}
My controller action looks like
public ActionResult _SelectionClientSide_Products()
{
IQueryable<Product> products = _repository.GetProducts(true);
var model = Mapper.Map<IEnumerable<Product>, IEnumerable<ProductViewModel>>(products);
return View(model);
}
I query for data using repository method and get IQueryable<Product> and map it to ProductViewModel list. But I also need to perform another query operation to count users for every queried product and assign all values to ProductViewModel. What design I should follow to achieve this?
The relationship between tables
Products -> Orders - > Users
EDIT
I have decided to remove AutoMapper because it gives more problems than benefits and created my own Builder which contain everything what I need. I make field assign and also add calculation.
public ActionResult _SelectionClientSide_Products()
{
Data = new ProductViewModelBuilder(_repository).Build();
return View(Data);
}
namespace PC.Models
{
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int UsersCount { get; set; }
}
public class ProductViewModelBuilder
{
private readonly IDataAccess _repository;
public ProductViewModelBuilder(IDataAccess repository)
{
_repository = repository;
}
public IQueryable<ProductViewModel> Build()
{
return _repository.GetProducts().Select(p=> new ProductViewModel
{
Id = p.Id,
Name = p.Name,
UsersCount = _repository.CountUsers(p.Id)
});
}
}
}
In my opinion, by the time your Controller has begun it's model setup, there should be no more "logic" or talking to the model. Having a "builder" which queries the model again is bad practice. Not really "breaking" the MVC pattern, but still bad practice. Your ViewModel has a dependency on your DAL. Bad bad boy. :)
If you have to run another query, well that should be encapsulated in the original query. Instead of calling _repository.GetProducts, call a different method which not only gets the products, but get's the count as well. Create a DTO if necessary.
Then your controller should look like:
public ActionResult _SelectionClientSide_Products()
{
var someDto = _repository.GetProductsAndUserCount(true);
var model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);
return View(model);
}
Personally i go for generic repositories over specialized ones, as i don't want a IProductRepository interface with 50 signatures. I opt for LINQ IEnumerable<T> extensions (aka "pipes and filters") which allows complex queries to be built and remain in my domain.
So my version of the above would be:
public ActionResult _SelectionClientSide_Products()
{
var someDto = _productRepository.Find().WithSomeCondition(true).ToSomeDto();
var model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);
return View(model);
}
On a side note, why do you say AutoMapper causes you more problems that benefits? AutoMapper has saved me tons and tons of repetitive code. If you know how to use it properly, it's your best friend. Hands down the most important NuGet package in my current application.

EF and repository pattern - ending up with multiple DbContexts in one controller - any issues (performance, data integrity)?

Most of my knowledge of ASP.NET MVC 3 comes from reading through the book Pro ASP.NET MVC 3 Framework by Adam Freeman and Steven Senderson. For my test application I have tried to stick to their examples very closely. I am using the repository pattern plus Ninject and Moq which means that unit testing work quite well (i.e. without needing to pull data from the database).
In the book repositories are used like this:
public class EFDbTestChildRepository
{
private EFDbContext context = new EFDbContext();
public IQueryable<TestChild> TestChildren
{
get { return context.TestChildren; }
}
public void SaveTestChild(TestChild testChild)
{
if (testChild.TestChildID == 0)
{
context.TestChildren.Add(testChild);
}
else
{
context.Entry(testChild).State = EntityState.Modified;
}
context.SaveChanges();
}
}
And here is the DbContext that goes with it:
public class EFDbContext : DbContext
{
public DbSet<TestParent> TestParents { get; set; }
public DbSet<TestChild> TestChildren { get; set; }
}
Please note: to keep things simple in this extracted example I have left out the interface ITestChildRepository here which Ninject would then use.
In other sources I have seen a more general approach for the repository where one single repository is enough for the whole application. Obviously in my case I end up with quite a list of repositories in my application - basically one for each entity in my domain model. Not sure about the pros and cons about the two approaches - I just followed the book to be on the safe side.
To finally get to my question: each repository has its own DbContext - private EFDbContext context = new EFDbContext();. Do I risk ending up with multiple DbContexts within one request? And would that lead to any significant performance overhead? How about a potential for conflicts between the contexts and any consequences to the data integrity?
Here is an example where I ended up with more than one repository within a controller.
My two database tables are linked with a foreign key relationship. My domain model classes:
public class TestParent
{
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
public virtual ICollection<TestChild> TestChildren { get; set; }
}
public class TestChild
{
public int TestChildID { get; set; }
public int TestParentID { get; set; }
public string Name { get; set; }
public string Comment { get; set; }
public virtual TestParent TestParent { get; set; }
}
The web application contains a page that allows the user to create a new TestChild. On it there is a selectbox that contains a list of available TestParents to pick from. This is what my controller looks like:
public class ChildController : Controller
{
private EFDbTestParentRepository testParentRepository = new EFDbTestParentRepository();
private EFDbTestChildRepository testChildRepository = new EFDbTestChildRepository();
public ActionResult List()
{
return View(testChildRepository.TestChildren);
}
public ViewResult Edit(int testChildID)
{
ChildViewModel cvm = new ChildViewModel();
cvm.TestChild = testChildRepository.TestChildren.First(tc => tc.TestChildID == testChildID);
cvm.TestParents = testParentRepository.TestParents;
return View(cvm);
}
public ViewResult Create()
{
ChildViewModel cvm = new ChildViewModel();
cvm.TestChild = new TestChild();
cvm.TestParents = testParentRepository.TestParents;
return View("Edit", cvm);
}
[HttpPost]
public ActionResult Edit(TestChild testChild)
{
try
{
if (ModelState.IsValid)
{
testChildRepository.SaveTestChild(testChild);
TempData["message"] = string.Format("Changes to test child have been saved: {0} (ID = {1})",
testChild.Name,
testChild.TestChildID);
return RedirectToAction("List");
}
}
catch (DataException)
{
//Log the error (add a variable name after DataException)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
// something wrong with the data values
return View(testChild);
}
}
It's not enough to have an EFDbTestChildRepository available but I also need an EFDbTestParentRepository. Both of them are assigned to private variables of the controller - and voila, it seems to me that two DbContexts have been created. Or is that not correct?
To avoid the issue I tried using EFDbTestChildRepository to get to the TestParents. But that obviously will only bring up those that are already hooked up to at least one TestChild - so not what I want.
Here is the code for the view model:
public class ChildViewModel
{
public TestChild TestChild { get; set; }
public IQueryable<TestParent> TestParents { get; set; }
}
Please let me know if I forgot to include some relevant code. Thanks so much for your advice!
There won't be a performance problem (unless we are talking about nanoseconds, instantiating a context is very cheap) and you won't have damaged your data integrity (before that happens you'll get exceptions).
But the approach is very limited and will work only in very simple situations. Multiple contexts will lead to problems in many scenarios. As an example: Suppose you want to create a new child for an existing parent and would try it with the following code:
var parent = parentRepo.TestParents.Single(p => p.Id == 1);
var child = new Child { TestParent = parent };
childrenRepo.SaveTestChild(child);
This simple code won't work because parent is already attached to the context inside of parentRepo but childrenRepo.SaveTestChild will try to attach it to the context inside of childrenRepo which will cause an exception because an entity must not be attached to another context. (Here is actually a workaround because you could set the FK property instead of loading the parent: child.TestParentID = 1. But without a FK property it would be a problem.)
How to solve such a problem?
One approach could be to extend the EFDbTestChildRepository by a new property:
public IQueryable<TestParent> TestParents
{
get { return context.TestParents; }
}
In the example code above you could then use only one repository and the code would work. But as you can see, the name "EFDbTest Child Repository" doesn't really fit anymore to the purpose of the new repository. It should be now "EFDbTest ParentAndChild Repository".
I would call this the Aggregate Root approach which means that you create one repository not for only one entity but for a few entities which are closely related to each other and have navigation properties between them.
An alternative solution is to inject the context into the repositories (instead of creating it in the repositories) to make sure that every repository uses the same context. (The context is often abstracted into a IUnitOfWork interface.) Example:
public class MyController : Controller
{
private readonly MyContext _context;
public MyController()
{
_context = new MyContext();
}
public ActionResult SomeAction(...)
{
var parentRepo = new EFDbTestParentRepository(_context);
var childRepo = new EFDbTestChildRepository(_context);
//...
}
protected override void Dispose(bool disposing)
{
_context.Dispose();
base.Dispose(disposing);
}
}
This gives you a single context per controller you can use in multiple repositories.
The next step might be to create a single context per request by dependency injection, like...
private readonly MyContext _context;
public MyController(MyContext context)
{
_context = context;
}
...and then configuring the IOC container to create a single context instance which gets injected into perhaps multiple controllers.
Do I risk ending up with multiple DbContexts within one request?
Yes. Each instance of a repository is going to instantiate its own DbContexts instances. Depending on the size and use of the application, this may not be a problem although it is not a very scalable approach. There are several ways of handling this though. In my web projects I add the DbContext(s) to the Request's Context.Item collection, this way it is available to all classes that require it. I use Autofac (similar to Ninject) to control what DbContexts are created within specific scenarios and how they are stored, e.g. I have a different 'session manager' for a WCF context to the one for a Http context.
And would that lead to any significant performance overhead?
Yes, but again not massively if the application is relatively small. As it grows though, you may notice the overhead.
How about a potential for conflicts between the contexts and any
consequences to the data integrity?
One of the reasons for using an ORM like this is so that changes can be maintained within the DbContext. If you are instantiating multiple context instances per request you lose this benefit. You wouldn't notice conflicts or any impact of the integrity per se unless you were handling a lot of updates asynchronously.
As promised I post my solution.
I came across your question because I was having trouble with the IIS application pool memory growing beyond limits and having multiple DBContexts was one of my suspects. In retrospect it is fair to say that there were other causes for my trouble. However, it challenged me to find a better layer based design for my repository.
I found this excellent blog: Correct use of Repository and Unit Of Work patterns in ASP.NET MVC leading me to the right direction. The redesign is based on the UnitOfWork pattern. It enables me to have just one constructor parameter for all my controllers instead of "never ending constructor parameters". And after that, I was able to introduce proactive caching as well, which solved a great deal of the earlier mentioned trouble I was having.
Now I only have these classes:
IUnitOfWork
EFUnitOfWork
IGenericRepository
EFGenericRepository
See the referred blog for complete information and implementation of these classes. Just to give an example, IUnitOfWork contains repository definitions for all entities that I need, like:
namespace MyWebApp.Domain.Abstract
{
public interface IUnitOfWork : IDisposable
{
IGenericRepository<AAAAA> AAAAARepository { get; }
IGenericRepository<BBBBB> BBBBBRepository { get; }
IGenericRepository<CCCCC> CCCCCRepository { get; }
IGenericRepository<DDDDD> DDDDDRepository { get; }
// etc.
string Commit();
}
}
The Dependency Injection (DI) is just one statement (I use Ninject):
ninjectKernel.Bind<IUnitOfWork>().To<EFUnitOfWork>();
The Controllers-constructors are maintainable:
public class MyController : BaseController
{
private MyModel mdl = new MyModel();
private IUnitOfWork _context;
public MyController(IUnitOfWork unitOfWork)
{
_context = unitOfWork;
// intialize whatever needs to be exposed to the View:
mdl.whatever = unitOfWork.SomeRepository.AsQueryable();
}
// etc.
Within the Controller I can use _context to access all repositories, if needed. The nice part of it, is that it needs just a single Commit()-call to save changed data for all repositories:
_context.Commit();

MVC3 load common data for views

I am developing an MVC3 "movie list" application containing several "sites" depending on the request hostname.
I am trying to use a strongly typed ViewModel like this (examples are simplified to get to the essence of the question):
class ViewModelBase
{
public int siteId { get; private set; }
public ViewModelBase(DbContext db)
{
siteId = <here I want to make a db-lookup based on the request hostname> <== This is my problem
}
}
class MoviesIndexViewModel : ViewModelBase
{
public List<Movie> movies { get; private set; }
public MoviesIndexViewModel(DbContext db) : base(db)
{
movies = db.Movies.where(m => m.SiteId == siteId).ToList();
}
}
An my controller would then just do this:
public class MoviesController : Controller
{
public ActionResult Index()
{
var model = new MoviesIndexViewModel(new MySpecialDbContext());
return View(model);
}
}
Question is: How will I get the "request host header" into the code line shown above? I know how to make the actual DB-lookup, but can I just access any request parameters here? Or should I supply something through parameters to the constructor?
I would not use Dbcontext in my view models. Read about Separation of concerns
Instead, use OnResultExecuting in your BaseController to add the common data:
protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
var baseModel = filterContext.Controller.ViewData.Model as YourCustomModel;
if (baseModel != null)
{
// call a repository or whatever to add information to the model.
}
base.OnResultExecuting(filterContext);
}
Update
yes. The controller is the glue between the "model" (repositores, webservices or any other data source) and the view. The ViewModel is just an abstraction to move away logic from the view.
Here is the three main reasons you should use a view model:
http://blog.gauffin.org/2011/07/three-reasons-to-why-you-should-use-view-models/
And an alternative approach to handle common view data: http://blog.gauffin.org/2011/09/getting-information-into-the-layout-without-using-viewbag/

Validation in a Domain Driven Design

How do you deal with validation on complex aggregates in a domain driven design? Are you consolidating your business rules/validation logic?
I understand argument validation and I understand property validation which can be attached to the models themselves and do things like check that an email address or zipcode is valid or that a first name has a minimum and maximum length.
But what about complex validation that involves multiple models? Where do you typically place these rules & methods within your architecture? And what patterns if any do you use to implement them?
Instead of relying on IsValid(xx) calls all over your application, consider taking some advice from Greg Young:
Don't ever let your entities get into
an invalid state.
What this basically means is that you transition from thinking of entities as pure data containers and more about objects with behaviors.
Consider the example of a person's address:
person.Address = "123 my street";
person.City = "Houston";
person.State = "TX";
person.Zip = 12345;
Between any of those calls your entity is invalid (because you would have properties that don't agree with each other. Now consider this:
person.ChangeAddress(.......);
all of the calls relating to the behavior of changing an address are now an atomic unit. Your entity is never invalid here.
If you take this idea of modeling behaviors rather than state, then you can reach a model that doesn't allow invalid entities.
For a good discussion on this, check out this infoq interview: http://www.infoq.com/interviews/greg-young-ddd
I like Jimmy Bogard's solution to this problem. He has a post on his blog titled "Entity validation with visitors and extension methods" in which he presents a very elegant approach to entity validation that suggest the implementation of a separate class to store validation code.
public interface IValidator<T>
{
bool IsValid(T entity);
IEnumerable<string> BrokenRules(T entity);
}
public class OrderPersistenceValidator : IValidator<Order>
{
public bool IsValid(Order entity)
{
return BrokenRules(entity).Count() == 0;
}
public IEnumerable<string> BrokenRules(Order entity)
{
if (entity.Id < 0)
yield return "Id cannot be less than 0.";
if (string.IsNullOrEmpty(entity.Customer))
yield return "Must include a customer.";
yield break;
}
}
I usualy use a specification class,
it provides a method (this is C# but you can translate it in any language) :
bool IsVerifiedBy(TEntity candidate)
This method performs a complete check of the candidate and its relations.
You can use arguments in the specification class to make it parametrized, like a check level...
You can also add a method to know why the candidate did not verify the specification :
IEnumerable<string> BrokenRules(TEntity canditate)
You can simply decide to implement the first method like this :
bool IsVerifiedBy(TEntity candidate)
{
return BrokenRules(candidate).IsEmpty();
}
For broken rules, I usualy write an iterator :
IEnumerable<string> BrokenRules(TEntity candidate)
{
if (someComplexCondition)
yield return "Message describing cleary what is wrong...";
if (someOtherCondition)
yield return
string.Format("The amount should not be {0} when the state is {1}",
amount, state);
}
For localization, you should use resources, and why not pass a culture to the BrokenRules method.
I place this classes in the model namespace with names that suggest their use.
Multiple model validation should be going through your aggregate root. If you have to validate across aggregate roots, you probably have a design flaw.
The way I do validation for aggregates is to return a response interface that tells me if validation pass/fail and any messages about why it failed.
You can validate all the sub-models on the aggregate root so they remain consistent.
// Command Response class to return from public methods that change your model
public interface ICommandResponse
{
CommandResult Result { get; }
IEnumerable<string> Messages { get; }
}
// The result options
public enum CommandResult
{
Success = 0,
Fail = 1
}
// My default implementation
public class CommandResponse : ICommandResponse
{
public CommandResponse(CommandResult result)
{
Result = result;
}
public CommandResponse(CommandResult result, params string[] messages) : this(result)
{
Messages = messages;
}
public CommandResponse(CommandResult result, IEnumerable<string> messages) : this(result)
{
Messages = messages;
}
public CommandResult Result { get; private set; }
public IEnumerable<string> Messages { get; private set; }
}
// usage
public class SomeAggregateRoot
{
public string SomeProperty { get; private set; }
public ICommandResponse ChangeSomeProperty(string newProperty)
{
if(newProperty == null)
{
return new CommandResponse(CommandResult.Fail, "Some property cannot be changed to null");
}
SomeProperty = newProperty;
return new CommandResponse(CommandResult.Success);
}
}
This questions a bit old now but in case anyone is interested here's how I implement validation in my service classes.
I have a private Validate method in each of my service classes that takes an entity instance and action being performed, if validation fails a custom exception is thrown with the details of the broken rules.
Example DocumentService with built in validation
public class DocumentService : IDocumentService
{
private IRepository<Document> _documentRepository;
public DocumentService(IRepository<Document> documentRepository)
{
_documentRepository = documentRepository;
}
public void Create(Document document)
{
Validate(document, Action.Create);
document.CreatedDate = DateTime.Now;
_documentRepository.Create(document);
}
public void Update(Document document)
{
Validate(document, Action.Update);
_documentRepository.Update(document);
}
public void Delete(int id)
{
Validate(_documentRepository.GetById(id), Action.Delete);
_documentRepository.Delete(id);
}
public IList<Document> GetAll()
{
return _documentRepository
.GetAll()
.OrderByDescending(x => x.PublishDate)
.ToList();
}
public int GetAllCount()
{
return _documentRepository
.GetAll()
.Count();
}
public Document GetById(int id)
{
return _documentRepository.GetById(id);
}
// validation
private void Validate(Document document, Action action)
{
var brokenRules = new List<string>();
if (action == Action.Create || action == Action.Update)
{
if (string.IsNullOrWhiteSpace(document.Title))
brokenRules.Add("Title is required");
if (document.PublishDate == null)
brokenRules.Add("Publish Date is required");
}
if (brokenRules.Any())
throw new EntityException(string.Join("\r\n", brokenRules));
}
private enum Action
{
Create,
Update,
Delete
}
}
I like this approach because it allows me to put all my core validation logic in one place which keeps things simple.

Resources