MVC - Implementing OData without EF/DB but Application Service as data source - asp.net-mvc

We have a WCF application service layer which acts as DataService for our domain models defined in DB. We are writing new REST web services that will work on top of existing application service. Planning to use MVC Web API.
We want to expose our RESTFul APIs as OData endpoint. But looks like OData is tightly coupled with EnityFramework Data Model and Context.
The problem is we can't use EF dbcontext as we need to create objects by requesting them from backend application service and then map to the data model.
Is there a way to implement OData without DB but application service as data source.
Thanks,
M

Looking though the MSDN article introducing OData, it seems that while the scaffolding in Visual Studio is aimed at using OData with EF, you can still create controllers directly by deriving from EntitySetController:
public class PeopleController : EntitySetController<Person, int>
{
public override IQueryable<Person> Get()
{
// return your own non-EF data source
}
}
As long as you can get an IQueryable, you should be able to knock up an OData controller.

You can! The only problematic action you have to take care of is the get.
There are two ways:
Use ODataQueryOptions. It contains the parameters like skip, orderby, etc.
Sample
public class TestController : ODataController
{
public IEnumerable<TestModel> Get(ODataQueryOptions<TestModel> options)
{
var entities = new List<TestModel>()
{
new TestModel { Id = 1 },
new TestModel { Id = 2 },
new TestModel { Id = 3 },
new TestModel { Id = 4 },
new TestModel { Id = 5 },
new TestModel { Id = 6 }
};
//In this example, we use ApplyTo but you can build an adapter to your application service from the options parameter
return (IEnumerable<TestModel>)options.ApplyTo(entities.AsQueryable());
}
}
Implement your own IQueryable Provider that will query the application service. I didn't try this but I don't see any reason for it to not work.

Related

Multiple entities with one web api controller

I am building a mvc based website with ef6 code first type db. Right now i have a web api controller named Categories Controller that works nicely and shells out json data to my js requests.
// GET: api/Categories
public IQueryable<Category> GetCategories()
{
return db.Categories;
}
Now I need to wire up same for products, materials and some other entities. What I would like is something like :
//GET: api/Data/Categories
//GET: api/Data/Products
etc. all wired into one DataController. Is there a way to accomplish this?
For example one Data Controller, with separate region of code for all category specific api actions, product specific api actions and so on. Then I could do /api/Data/Categories/Create or api/Data/Products/Create
Instead of bringing in a new technology, you could handle this by creating a new class that contains both. I am assuming there is no relation between them, such as a Product has Categories, but rather you want both exclusively.
// GET: api/Data/ProductCategories
public IQueryable<ProductsCategory> GetProductsCategories()
{
return GetProductsCategories();
}
...
public class ProductsCategory
{
public IEnumerable<Category> Categories { get; set;}
public IEnumerable<Product> Products{ get; set;}
}
...
public ProductsCategory GetProductsCategories()
{
var products = db.Products.ToList();
var categories = db.Categories.ToList();
var productCategories = new ProductsCategory()
{
Products = products,
Categories = categories
};
return productCategories;
}
Or something to that degree.
Also don't return IQueryable directly, it's redundant and ill advised unless the caller of that API is going to somehow be executing some Query against what has been returned which is unlikey seeing as its WebAPI and not some method. Instead return a List or IEnumerable.
And if you are looking to improve what you have a little bit as well, be sure to wrap that repository that you have in some sort of service, so you can say something along the lines of:
productsService.GetProductsCategories()
Rather than accessing the context directly in your API.
Extended Reading for Repositories and Service Layers
https://codereview.stackexchange.com/questions/33109/repository-service-design-pattern
Difference between Repository and Service Layer?
The easiest way to do what you want is to implement an OData controller, or a Breeze controller. They will do all the heavylifting to expose your EF model to in Web APi endpoints:
OData
Breeze
They're wuite easy to setup and OData is a recognized standard for this kind of task. They both had prebuilt support for oldering, filtering, paging, including related conllections and so. There are Nuget packages to use both of them.
Breeze also has feature-rich clients for JS and C#, and a lot of extra functionality.

How do I define and use a repository using the AutoMapper DestinationType?

I'm trying to reduce duplicated code in an existing MVC 4 Web API 2 application. We are using AutoMapper to map the entities to custom DataObjects. We have an existing database that has multiple tables for 'Tags' pertaining to specific products (let's say bicycle, couch, and table).
I have a generic controller:
public class TagController<TTagDataObject> : ApiController where TTagDataObject : ITagDataObject
{
private readonly ITagService<TTagDataObject> _service;
public TagController(ITagService<TTagDataObject> service)
{
_service = service;
}
[HttpPost]
public HttpResponseMessage Post(TTagDataObject model)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ModelState);
}
// Make service call
model = _service.CreateTag(model);
return Request.CreateResponse(HttpStatusCode.Created, model);
}
... Other Methods
}
The application is using the Repository Pattern, and I'm having trouble creating the service because I need to define the Repository by entity type, and I only know the DataObject type.
I can get the Entity type using AutoMapper's GetAllTypeMaps()
System.Type t = Mapper.GetAllTypeMaps().FirstOrDefault(i=> i.SourceType == typeof(TTagDataObject)).DestinationType;
How do I define and use the repository? I'd like to do something like:
Repository<t> repository = new Repository<t>();
But I get "The type or namespace 't' could not be found..."
I can define the repository using the Activator CreateInstance method as in this question: Pass An Instantiated System.Type as a Type Parameter for a Generic Class
var repository = Activator.CreateInstance(t);
But then unless I use reflection or dynamics I can't access the repository methods. It seems like there should be a much simpler solution to this, and am open to the possibility that I'm going about this the wrong way.
Thank you very much.

ASP .NET Web API Queryable capabilities with deferred execution

Should my api method always tie up to the underlying datasource (datacontext of an ORM) to expose Queryable capabilities supporting oData with the benefit of Deferred Execution?
Snippet
public class ProductController : ApiController {
public IQueryable<Product> Get() {
var dbContext = new DBContext();
return dbContext.Product.AsQueryable();
}
}
If I have to tie the always then, how and where can I apply business validation if I have to ? Eg: I want to return on the Products which are not expired.
Aren't we violating the seperation of concerns and doing tight coupling by exposing the data entities directly?
You can have the rule applied as below:
return dbContext.Product.Where(p=> !p.IsExpired).AsQueryable();
With regard to your second question, it is up to you. If you need to expose your data, then you should. If you want to expose an alternate view of the data, you can create a ViewModel and expose that.

Difference between Repository and Service Layer?

In OOP Design Patterns, what is the difference between the Repository Pattern and a Service Layer?
I am working on an ASP.NET MVC 3 app, and am trying to understand these design patterns, but my brain is just not getting it...yet!!
Repository Layer gives you additional level of abstraction over data access. Instead of writing
var context = new DatabaseContext();
return CreateObjectQuery<Type>().Where(t => t.ID == param).First();
to get a single item from database, you use repository interface
public interface IRepository<T>
{
IQueryable<T> List();
bool Create(T item);
bool Delete(int id);
T Get(int id);
bool SaveChanges();
}
and call Get(id). Repository layer exposes basic CRUD operations.
Service layer exposes business logic, which uses repository. Example service could look like:
public interface IUserService
{
User GetByUserName(string userName);
string GetUserNameByEmail(string email);
bool EditBasicUserData(User user);
User GetUserByID(int id);
bool DeleteUser(int id);
IQueryable<User> ListUsers();
bool ChangePassword(string userName, string newPassword);
bool SendPasswordReminder(string userName);
bool RegisterNewUser(RegisterNewUserModel model);
}
While List() method of repository returns all users, ListUsers() of IUserService could return only ones, user has access to.
In ASP.NET MVC + EF + SQL SERVER, I have this flow of communication:
Views <- Controllers -> Service layer -> Repository layer -> EF -> SQL Server
Service layer -> Repository layer -> EF This part operates on models.
Views <- Controllers -> Service layer This part operates on view models.
EDIT:
Example of flow for /Orders/ByClient/5 (we want to see order for specific client):
public class OrderController
{
private IOrderService _orderService;
public OrderController(IOrderService orderService)
{
_orderService = orderService; // injected by IOC container
}
public ActionResult ByClient(int id)
{
var model = _orderService.GetByClient(id);
return View(model);
}
}
This is interface for order service:
public interface IOrderService
{
OrdersByClientViewModel GetByClient(int id);
}
This interface returns view model:
public class OrdersByClientViewModel
{
CientViewModel Client { get; set; } //instead of ClientView, in simple project EF Client class could be used
IEnumerable<OrderViewModel> Orders { get; set; }
}
This is interface implementation. It uses model classes and repository to create view model:
public class OrderService : IOrderService
{
IRepository<Client> _clientRepository;
public OrderService(IRepository<Client> clientRepository)
{
_clientRepository = clientRepository; //injected
}
public OrdersByClientViewModel GetByClient(int id)
{
return _clientRepository.Get(id).Select(c =>
new OrdersByClientViewModel
{
Cient = new ClientViewModel { ...init with values from c...}
Orders = c.Orders.Select(o => new OrderViewModel { ...init with values from o...}
}
);
}
}
As Carnotaurus said the repository is responsible for mapping your data from the storage format to you business objects. It should handle both how to read and write data(delete, update too) from and to the storage.
The purpose of service layer on the other hand is to encapsulate business logic into a single place to promote code reuse and separations of concerns. What this typically means for me in practice when building Asp.net MVC sites is that I have this structure
[Controller] calls [Service(s)] who calls [repository(ies)]
One principle I have found useful is to keep logic to a minimum in controllers and repositories.
In controllers it is because it helps keeping me DRY. It's very common that I need to use the same filtering or logic somewhere else and if I placed it in the controller I can't reuse it.
In repositories it is because I want to be able to replace my storage(or ORM) when something better comes along. And if I have logic in the repository I need to rewrite this logic when I change the repository. If my repository only returns IQueryable and the service does the filtering on the other hand, I will only need to replace the mappings.
For example I recently replaced several of my Linq-To-Sql repositories with EF4 and those where I had stayed true to this principle could replaced in a matter of minutes. Where I had some logic it was a matter of hours instead.
The accepted answer (and upvoted hundreds of time) has a major flaw. I wanted to point this out in the comment but it will just get buried down there in 30 something comments so pointing out here.
I took over an enterprise application which was built that way and my initial reaction was WTH? ViewModels in service layer? I did not want to change the convention because years of development had gone into it so I continued with returning ViewModels. Boy it turned into a nightmare when we started using WPF. We (the team of devs) were always saying: which ViewModel? The real one (the one we wrote for the WPF) or the services one? They were written for a web application and even had IsReadOnly flag to disable edit in the UI. Major, major flaw and all because of one word: ViewModel!!
Before you make the same mistake, here are some more reasons in addition to my story above:
Returning a ViewModel from the service layer is a huge no no. That's like saying:
If you want to use these services you better be using MVVM and here is the ViewModel you need to use. Ouch!
The services are making the assumption they will be displayed in a UI somewhere. What if it is used by a non UI application such as web services or windows services?
That is not even a real ViewModel. A real ViewModel has observability, commands etc. That is just a POCO with a bad name. (See my story above for why names matter.)
The consuming application better be a presentation layer (ViewModels are used by this layer) and it better understand C#. Another Ouch!
Please, don't do that!
Repository layer is implemented to access the database and helps to extend the CRUD operations on the database. Whereas a service layer consists of the business logic of the application and may use the repository layer to implement certain logic involving the database. In an application, it is better to have a separate repository layer and service layer. Having separate repository and service layers make the code more modular and decouple the database from business logic.
Usually a repository is used as scaffolding to populate your entities - a service layer would go out and source a request. It is likely that you would put a repository under your service layer.

How to use a DI / IoC container with the model binder in ASP.NET MVC 2+?

Let's say I have an User entity and I would want to set it's CreationTime property in the constructor to DateTime.Now. But being a unit test adopter I don't want to access DateTime.Now directly but use an ITimeProvider :
public class User {
public User(ITimeProvider timeProvider) {
// ...
this.CreationTime = timeProvider.Now;
}
// .....
}
public interface ITimeProvider {
public DateTime Now { get; }
}
public class TimeProvider : ITimeProvider {
public DateTime Now { get { return DateTime.Now; } }
}
I am using NInject 2 in my ASP.NET MVC 2.0 application. I have a UserController and two Create methods (one for GET and one for POST). The one for GET is straight forward but the one for POST is not so straight and not so forward :P because I need to mess with the model binder to tell it to get a reference of an implementation of ITimeProvider in order to be able to construct an user instance.
public class UserController : Controller {
[HttpGet]
public ViewResult Create() {
return View();
}
[HttpPost]
public ActionResult Create(User user) {
// ...
}
}
I would also like to be able to keep all the features of the default model binder.
Any chance to solve this simple/elegant/etc? :D
A couple of observations:
Don't inject dependencies just to query them in the constructor
There's no reason to inject an ITimeProvider into a user just to invoke Now immediately. Just inject the creation time directly instead:
public User(DateTime creationTime)
{
this.CreationTime = creationTime;
}
A really good rule of thumb related to DI is that constructors should perform no logic.
Don't use DI with ModelBinders
An ASP.NET MVC ModelBinder is a really poor place to do DI, particularly because you can't use Constructor Injection. The only remaining option is the static Service Locator anti-pattern.
A ModelBinder translates HTTP GET and POST information to a strongly typed object, but conceptually these types aren't domain objects, but similar to Data Transfer Objects.
A much better solution for ASP.NET MVC is to forego custom ModelBinders completely and instead explicitly embrace that what you receive from the HTTP connection is not your full domain object.
You can have a simple lookup or mapper to retrieve your domain object in your controller:
public ActionResult Create(UserPostModel userPost)
{
User u = this.userRepository.Lookup(userPost);
// ...
}
where this.userRepository is an injected dependency.
How about instead of using an ITimeProvider try this:
public class User
{
public Func<DateTime> DateTimeProvider = () => DateTime.Now;
public User()
{
this.CreationTime = DateTimeProvider();
}
}
And in your unit test:
var user = new User();
user.DateTimeProvider = () => new DateTime(2010, 5, 24);
I know that this is not very elegant but instead of messing with the model binder this could be a solution. If this doesn't feel like a good solution you could implement a custom model binder and override the CreateModel method where you would inject the dependencies in the constructor of the model.
Another option is to create a different class to represent users that haven't been persisted yet that doesn't have a creation date property at all.
Even if CreationDate is one of User's invariants, it can be nullable in your view model - and you can set it farther downstream, in your controller or domain layer.
After all, it probably doesn't matter, but should the creation date attribute really represent the moment you construct a user instance, or would it be more appropriate for it to represent the moment a user submits their data?

Resources