I am new to IoC and Repository Pattern. I was able to do some test project and it works. But, I am not so sure if what I implemented is a good practice. The test project I have created have all the repositories in place as well as a working interface with a dummy data. But what I want is that my project should not be able to know the concrete types of my models because the initial version should be implemented using MSSQL, and the second version would be a mix of MSSQL and NoSQL(for reads and logging). The models might have different properties or structures from MSSQL to NoSQL (or whatever i might use in the future)
So I tried to create an interface for each model:
public interface ISearchResult
{
string Id { get; set; }
string Name { get; set; }
string Description { get; set; }
string Url { get; set; }
}
And here's the repository:
public interface ISearchRepository<T> where T: class, ISearchResult
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
And here's the service:
public interface ISearchService
{
IEnumerable<T> Search<T>(string keyword, IEnumerable<string> regions, IEnumerable<string> industries,IEnumerable<string> countries, IEnumerable<string> cities, int offset);
}
Because I want to have a working GUI even without MSSQL or NoSQL entities, I have created a View Model that inherited the ISearchResult:
public class SearchResultViewModel : ISearchResult
{
[Display(Name="Reference Id")]
public string Id { get; set; }
[Display(Name = "Company")]
public string Name { get; set; }
[Display(Name = "Description")]
public string Description { get; set; }
[Display(Name = "Website")]
public string Url { get; set; }
}
And here's how it looks on my controller:
[SearchQueryFilter]
[GeoTargetFilter]
public ActionResult Query(SearchQueryModel searchQuery)
{
searchQuery.Results = this._searchService.Search<SearchResultViewModel>(searchQuery.Keyword,searchQuery.Region, new List<string>() { searchQuery.Industries }, new List<string>() { searchQuery.Countries}, new List<string>() {searchQuery.City}, searchQuery.Offset)
.ToList<ISearchResult>();
return View(searchQuery);
}
And my view would look like this:
#foreach (SearchResultViewModel result in Model.Results)
{
//code to display
}
My question is: Is it fine to use this approach? I don't want my web application to be dependent on my data entities so that's why I came up of making my view models inherit an interface. And because I was new to IoC and Repository Pattern and only have a test project, I don't know if my solution would be more of a problem in the long run.
Any advise is highly appreciated.
You shouldn't need to implement an interface in your view model in order to create a separation between your web application and your data entities. Your view model should belong to your web application and should itself be independent of your data entity.
So, instead of:
_searchService.Search<SearchResultViewModel>(x);
You should have, in your controller:
var result = _searchService.Search<SomeEntity>(x);
var model = new SearchResultsViewModel
{
Name = result.Name,
Desc = result.Desc,
Url = result.Url
};
return View(model);
The view model belongs to the web application and is responsible for containing the data passed from controller to view (and back) - it should have nothing to do with your service layer (or any other layer of your application).
SomeEntity is a concrete class, in the form of whatever your search service exposes. Your controller will consume this in the same way as any other application would and then compile a view model for passing to and from views. You might even find that SomeEntity is more or less identical to SearchResultsViewModel initially; however, they are still distinct entities as the requirements of the view might change independently of the search service.
Related
I want to accept different model type from body based on query param value.
Example:
[HttpGet]
[Route("GetSystemdetails")]
public string Getdeatils([FromBody] SystemDetail sysdetails, string type)
{
//some code here
string details = getdetails(sysdetails);
}
// abc model
public class abc
{
public int UserID { get; set; }
public string Email { get; set; }
}
//xyz model
public class xyz
{
public int xyzid { get; set; }
public string systemval { get; set; }
public string snum { get; set; }
}
type abc and xyz will have it's own model. So based on type I receive in query param I wanted to pick the model and proceed.
Sample url:
localhost/GetSystemdetails/type=abc
localhost/GetSystemdetails/type=xyz
I thought of creating a new model SystemDetail which holds these two models(xyz and abc) and based on system pick them.
I wanted to know what are possible ways to achieve this kind of requirements without creating multiple methods in controller(I don't want to change the format of the URL).
That's not something that's supported out of the box. Your linked solution is probably the closest you'll get to that.
ASP.NET Core is not supposed to take values of the parameters into account when routing, except for validation.
There are several possible ways to do so
Having multiple model objects
As in the link you provided, you can declare multiple model objects. The site has given the example of
public class PostUserGCM
{
public User User { get; set; }
public GCM GCM { get; set; }
}
but you can use your own examples.
Base model
Your models can inherit from some base model. If you only need a single model at a time and they share some similarities, then you could just create a base model which the other two are inheriting from, be agnostic at implementation time and your use cases will mainly differ on instantiation inside the controller, while some service methods could handle other differences.
I want to use view model for displaying instead of domain model. I have got these view models classes:
public class ArticleDescriptionViewModel
{
public string Title { get; set; }
public DateTime DateCreated { get; set; }
}
public class HomePage
{
public List<ArticleDescriptionViewModel> Articles { get; set; }
}
In the domain model i have got:
public class ArticleDescription
{
public string Title { get; set; }
public DateTime DateCreated { get; set; }
}
And this service method:
public List<ArticleDescription> GetArticlesDescription()
{
var articleDescription= from a in _ctx.Articles
select new ArticleDescription
{ Title = a.Title, DateCreated = a.DateCreated };
return articleDescription.ToList();
}
in the controller i want to match my list inside of my view model class with the list returned by my domain model class.
public ActionResult Index()
{
HomePage HomePageInstance = new HomePage();
HomePageInstance.Articles = _repo.GetArticlesDescription();
return View(HomePageInstance);
}
I have got an error:
"Cannot implicitly convert type System.Collections.Generic.List (DBayonaCode.Domain.Services.Models.ArticleDescription)' to 'System.Collections.Generic.List(DBayonaCode.Models.ArticleDescriptionViewModel)'"
But these two classes are equivalent? I am doing something wrong. I appreciate your help?
ArticleDescription and ArticleDescriptionViewModel are two different types, so there's no implicit conversion between them. You need to map your Domain Model object to your View Model object, you can do that either manually or with a tool like AutoMapper.
You could write extension methods like these to do the mapping:
public static class Mappings
{
public static ArticleDescriptionViewModel ConvertToView(this ArticleDescription article)
{
// Mapping Code
// return new ArticleDescriptionViewModel { ... }
}
public static List<ArticleDescriptionViewModel> ConvertToViews(this List<ArticleDescription> articles)
{
List<ArticleDescriptionViewModel> articleViews = new List<ArticleDescriptionViewModel>();
foreach (ArticleDescription article in articles)
{
articleViews.Add(article.ConvertToView())
}
return articleViews;
}
}
While MVC default project template offer just one model folder, thus implicitly presenting the idea that models are one thing, in fact There are three types of data models potentially involved in an ASP.NET MVC application:
- Domain model objects will be passed from and to a middle tier services interfacing with databases.
- View Model objects are those that the Controller pass to the View.
- Input model objects are those that the default modelBinder or some custom modelBinder generates from the view, although in many cases the input models are the same view model objects.
Hope it helps.
I am new to MVC programming. In normal OOP, where I have my class, I would just initiliaze and load data from database. In MVC, we have modules, how do I load up records from it?
Here is my current code for type UserAcount:
[Table("UserAccount")]
public class UserAccount {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string userName { get; set; }
public string email { get; set; }
public int companyID { get; set; }
}
Say that I have an user with name "testUser", how do I initialize on this record and get it's information? How do I do this:
UserAccount user = new UserAccount("tesetUser");
How and where shoulud I use this?
user = user.SingleOrDefault(u => u.userName.ToLower() == User.Identity.Name.ToLower());
You need to read up on Entity Framework. This is the default ORM that MVC uses. Simply:
If you don't have a project context, yet, create one:
public class MyProjectContext : DbContext
{
public MyProjectContext()
: base("name=ConnectionStringNameHere")
{
}
}
Add your models to your project context:
public class MyProjectContext : DbContext
{
...
public DbSet<SomeModel> SomeModels { get; set; }
public DbSet<SomeOtherModel> SomeOtherModels { get; set; }
# etc.
}
Update your database using Package Manager Console (TOOLS > Library Package Manager > Package Manager Console):
> update-database
(hit ENTER after typing that)
Now, to use your context in your controllers:
public class MyAwesomeController : Controller
{
private MyProjectContext db = new MyProjectContext();
public ActionResult Index()
{
var someModels = db.SomeModels;
return View(someModels);
}
public ActionResult GetSomeModel(int id)
{
var someModel = db.SomeModels.Find(id);
return View(someModel);
}
# other actions
}
In the simplest case, you should do this logic in your controller, which will pass the data to the view. However, MVC is meant for UI separation of concerns, so theoretically you should be doing this in your domain layer, which is called from your controller.
Here is a decent article from Jeff Atwood, however I disagree that the controller is the brains of the application. It is more of the brains of the UI...but that depends on how complex your code is. Dont create a domain layer if it is stupidly simple
In the MVC model, Controllers are responsible for processing HTTP requests.
Typically you would load your entity (e.g. UserAccount) in a controller action.
If you want to edit / update an entity, typically you would map the relevant fields to a model that reflects the UserAccount. A separate model is suggested because the needs of the UI are often somewhat different than the needs of the entity model. Having separate classes for each concern avoids polluting the entity model to satisfy the needs of the view.
In my solution I have two projects.
Project 1 (Core)
Mapping SQL to DTO using Dapper
Project 2 (WebUI - ASP.NET MVC 4)
Here I use a ViewModel per View.
Examples of a Controller
[HttpGet]
public ActionResult Edit(int id)
{
// Get my ProductDto in Core
var product = Using<ProductService>().Single(id);
var vm = new ProductFormModel(product);
return View(vm);
}
Examples of a ViewModel
public class ProductFormModel : BaseViewModel, ICreateProductCommand
{
public int ProductId { get; set; }
public int ProductGroupId { get; set; }
public string ArtNo { get; set; }
public bool IsDefault { get; set; }
public string Description { get; set; }
public string Specification { get; set; }
public string Unit { get; set; }
public string Account { get; set; }
public decimal NetPrice { get; set; }
public ProductFormModel(int productGroupId)
{
this.ProductGroupId = productGroupId;
}
public ProductFormModel(ProductDto dto)
{
this.ProductId = dto.ProductId;
this.ProductGroupId = dto.ProductGroupId;
this.ArtNo = dto.ArtNo;
this.IsDefault = dto.IsDefault;
this.Description = dto.Description;
this.Specification = dto.Specification;
this.Unit = dto.Unit;
this.Account = dto.Account;
this.NetPrice = dto.NetPrice;
}
public ProductFormModel()
{
}
}
Explanation:
I'll get my DTOs in my controller using a service class in the project (Core).
Then i create my ViewModel and pass the DTO to the constructor in ViewModel.
I can also use this view to add a new Product because my ViewModel can take a empty constructor.
Does anyone have experience of this. I wonder if I am in this way will have problems in the future as the project gets bigger?
I know this has nothing to do with Dapper. But I would still like a good way to explain my solution.
I think you will be fine using your current approach. More importantly, start out like this and refactor if you start to encounter problems related to your object mapping code (instead of thinking too much about it beforehand).
Another way to organize mapping logic that I use sometimes is to employ extension methods. That way, the mapping code is kept separate from the view model itself. Something like:
public static class ProductMappingExtensions
{
public static ProductFormModel ToViewModel(this ProductDto dto)
{
// Mapping code goes here
}
}
// Usage:
var viewModel = dto.ToViewModel();
Yet another approach would be to use a mapping framework like AutoMapper - this is a good fit in particular if your mapping logic is simple (lots of 1:1 mappings between properties).
But again, start simple and refactor when you need to.
I realize that this is a little bit late answer, but maybe it will help someone in the future.
This way of doing mapping between objects breaks the 'S' of the SOLID principles, because the responsibility of the ViewModel is to prepare data in its properties to be ready to use by the view and nothing else, therefore, mapping objects should not be on it's responsibilities.
Another drawback of this way is that it also breaks the 'Loose Coupling' OO principle as you ViewModel is strongly coupled with your DTO.
I think, even when we are in the very first step of the project, there are some importants OO principles that we should never break, so using mapper classes, either auto (AutoMapper, ValueInjecter ...) or manual, is definitely better.
I am learning MVC 3 and I have not found people using some logic codes inside a property of a data model class.
They do the data model class as follows (for example):
public class Customer
{
public int CustomerId {get;set;}
//other properties without any logic code.
}
Is it ok to have logic codes inside a property as follows?
public class Customer
{
private int customerId;
public int CustomerId {
get{return customerId;}
set
{
customerId=value;
// some logic codes go here.
}
}
//other properties go here.
}
Edit 1:
This is my real scenario:
Child table data model:
namespace MvcApplication1.Models
{
public class Choice
{
public int ChoiceId { get; set; }
public string Description { get; set; }
public bool IsCorrect { get; set; }
public QuizItem QuizItem { get; set; }
}
}
Parent table data model:
namespace MvcApplication1.Models
{
public class QuizItem
{
public int QuizItemId { get; set; }
public string Question { get; set; }
private IEnumerable<Choice> choices;
public IEnumerable<Choice> Choices
{
get { return choices; }
set
{
choices = value;
foreach (var x in choices)
x.QuizItem = this;
}
}
}
}
Consumer:
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
var data = new List<QuizItem>{
new QuizItem
{
QuizItemId = 1,
Question = "What color is your hair?",
Choices = new Choice[]{
new Choice{ ChoiceId=1, Description="Black.", IsCorrect=true},
new Choice{ ChoiceId=2, Description="Red.", IsCorrect=false},
new Choice{ ChoiceId=3, Description="Yellow.", IsCorrect=false}
}
},
new QuizItem
{
QuizItemId = 2,
Question = "What color is your noze?",
Choices = new Choice[]{
new Choice{ChoiceId=1, Description="Pink.", IsCorrect=false},
new Choice{ChoiceId=2, Description="Maroon.", IsCorrect=true},
new Choice{ChoiceId=3, Description="Navy Blue.", IsCorrect=false}
}
}
};
return View(data);
}
}
}
This calls for a method. Two reasons why:
I don't recommend setters for Collections
Property Usage Guidelines - Setting a property for each item in collection every time property is set is expensive and should not be in a property. A method is preferred instead.
Code (that you have in your case) in setter causes enough side-effects to disqualify use of property
Setters for collection type properties - A discussion on StackOverflow regarding setters for collections.
I suggest following:
public class QuizItem
{
public int QuizItemId { get; set; }
public string Question { get; set; }
private IEnumerable<Choice> choices;
public IEnumerable<Choice> Choices
{
get { return choices; }
}
public void SetChoices(IEnumerable<Choice> choices)
{
foreach (var x in choices)
x.QuizItem = this;
this.choices = choices;
}
}
I think this logic you should implement in controller. However I always define POCO classes in my model and use ViewModel to implement such simple logic.
This is more of a realm of philosophical approach. As such it is up to a debate.
Today by far the most prevalent approach is to use strict layered approach of separation of concerns where "model" objects are only responsible for containing data and if you want to apply any sort of business logic on top of that, you need to implement that on a separate "business logic" layer, which handles application of such concerns as validation/vewrification of the integrity of data, mutation of data according to a business processes, etc.
Another approach is to use model layer to actually model (as in verb) the business of the target domain. In this case, the model acts as a direct definition of the business rules and should just as rich as rules of the business require it to be. (this approach has been taken to extreme by Naked Objects, that basically keeps data structures as well as business logic in the model and generates ORM, controller logic and views from the same model)
Generally the question of "how smart can/should be my model objects" is one to ask from the frameworks you use. Some frameworks simply don't care either way (ASP.NET MVC), others want you to never worry about coding this stuff, as long as you provide enough metadata so that they can do their job for you (NHibernate, Entity Framework). Others yet encourage you to express all your business rules and logic in the domain object model (e.g. Naked Objects)
In my opinion, a data model should be doing logic related to data (value) as in "is this value a valid data to...?". Also when doing hidden logic like in this case "attaching a parent", naming the method to just "set" is also wrong.
A sample of a more complex data model:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application