web api different field combinations on one single model - c#

Say I have the following model:
class Product
{
public string Id { get; set; }
public string Name { get; set; }
public string Brand { get; set; }
public string Description { get; set; }
public string Image { get; set; }
}
For a list view in the client I would only need the following:
class ProductListView
{
public string Name { get; set; }
public string Image { get; set; }
}
For a detail view I would need the following:
class ProductDetailView
{
public string Name { get; set; }
public string Brand { get; set; }
public string Description { get; set; }
public string Image { get; set; }
}
For an update of the name, I would need:
class ProductUpdateName
{
public string Id { get; set; }
public string Name { get; set; }
}
For an update of the description and brand, I would need:
class ProductUpdateDescriptionAndBrand
{
public string Id { get; set; }
public string Brand { get; set; }
public string Description { get; set; }
}
For all these different combinations, do I create the same number of classes? This sounds horrible though.
I can do anonymous classes instead but then I would need reflection to figure out the actual fields. This also sounds wrong.
So what is the best way?

A DTO by nature should represent a particular use case. The class is a representation of the data that will be transferred - hence the name. As such, whenever there's different data, yes, you should have a different DTO.
Now, that doesn't stop you from building upon your DTOs via inheritance. For example, ProductDetailView could inherit from ProductListView, since it is a superset of the properties of ProductListView. However, you should not inherit from ProductUpdateDescriptionAndBrand, because that includes an Id property, which ProductDetailView does not.
In those cases, you can opt to employ composition instead. For example, you could have something like:
public class BrandDescription
{
public string Brand { get; set; }
public string Description { get; set; }
}
And then:
public class ProductUpdateDescriptionAndBrand
{
public string Id { get; set; }
public BrandDescription BrandDescription { get; set; }
}
public class ProductDetailView : ProductListView
{
public BrandDescription BrandDescription { get; set; }
}
Otherwise, then just keep the classes as they are and use all of them as appropriate. Remember also that each of these serves a particular purpose (representing a particular group of data being transferred). As such, a property like Description, doesn't necessarily mean the same thing in all places. Just because the properties are similar or named the same doesn't mean they are handling the same concept(s).

Related

Concrete Classes with Properties or Dynamic Metadata Debate

So I'm currently debating the option of either defining concrete classes with properties, or to go with a metadata-type design. For example:
public class Employee
{
public Guid Id { get; set; }
public string Name { get; set; }
public string EmployeeCode { get; set; }
public string SpecialAssignment { get; set; }
public string SomeFutureProperty { get; set; }
}
Versus a key/value pair design which can be dynamic:
public class Employee
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<MetaKeyValue> Properties { get; set; }
}
public class MetaKey
{
public Guid Id { get; set; }
public string EntityType { get; set; } // could be a dictionary or enum
public string Name { get; set; }
public string Description { get; set; }
public string Required { get; set; }
}
public class MetaKeyValue
{
public Guid Id { get; set; }
public Guid EntityId { get; set; }
public Guid MetaKeyId { get; set; }
public string Value { get; set; } // string isn't the preferred object type
}
So, the debate is that I'm not sure which one is more efficient. The target persistence is a SQL database using Entity Framework. The beauty of the metadata design is that without modifying code and planning a deployment, new "properties" could be added to an entity and the values could be added and retrieved. The negative is that it's not what I'm accustomed to as I am an old-school coder who likes concrete classes that are statically defined. Would the dynamic design bite me in the rear later down the line?

ASP.NET MVC 5, how to enable validation annotation on viewmodel that composes other view models?

Well I have a very complex User Profile system in a social network application I am building. The profile page has tabs that distinguishes each category of user profile information: Basic, Education, Job. There is a UserProfileViewModel sitting on top of everything, which composes of inner view models such as BasicViewModel, EducationViewModel and JobViewModel. Consider the structure as below:
public class ProfileViewModel
{
public string id { get; set; }
public BasicViewModel basic { get; set; }
public EducationViewModel education { get; set; }
public JobViewModel job { get; set; }
}
public class BasicViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? DateOfRegistration { get; set; }
public DateTime? DateOfBirth { get; set; }
public string Gender { get; set; }
public string PhoneNumber { get; set; }
[Display(Name = "Biography")]
public string Biography { get; set; }
public string NickName { get; set; }
public string FavoriteQuotes { get; set; }
}
public class EducationViewModel{
public string EducationStatus { get; set; }
public List<University> Universities { get; set; }
public string CourseStatus { get; set; }
public string CourseSpecialization { get; set; }
public List<string> EducationEvents { get; set; }
}
public class JobViewModel
{
public string WorkStatus { get; set; }
public List<Company> Companies { get; set; }
}
public abstract class Organization
{
public string Name { get; set; }
public DateTime? Year { get; set; }
public int TimePeiod { get; set; }
}
public class University: Organization
{
public string Degree { get; set; }
public string Profession { get; set; }
}
public class Company: Organization
{
public string Website { get; set; }
public string Position { get; set; }
}
So the question is, does data annotation for model validation(both server and client side) work for a model that has composite structure like this? If so, do I just place annotation like I usually do with simple view models? If not, how can I achieve this in alternative ways? Please help.
Any single view model may contain other viewmodels like this:
This model is server side:
[Serializable]
public class MyBigViewModel : IValidatableObject
{
public MyBigViewModel(){
MyOtherViewModel = new MyOtherViewModel();
MyThirdViewModel = new MyThirdViewModel();
}
public MyOtherViewModel {get;set;}
public MyThiddViewModel {get;set;}
public void Post(){
//you can do something here based on post back
//like maybe this where the post method here processes new data
MyOtherViewModel.Post();
}
}
The controller could look like this:
public ActionResult UserList (MyBigViewModel uvm){
if(ModelState.IsValid){
uvm.Post();
return View(uvm);
}
return View(uvm);
}
You can implement the IValidateableObject to do "server side" validation. In the example above however, we want each viewmodel to "contain" it's own model for validation.
Each viewmodel property can use data annotations "contained" in only that viewmodel. It's a very nice way to "Contain" what you want where you want.
I very often use multiple Viewmodels in main VM and pass them in with partial views as needed.

Data travel from DAL to MVC View

ASP.NET MVC4
I have Business layer DLL which communicates to my DAL and retrieves classes like:
public class ProductionParameter
{
public string CompanyCode { get; set; }
public string UnitCode { get; set; }
public string ItemDescriptionLocal { get; set; }
public string ItemDescriptionEnglish { get; set; }
public string ConsumedItemDescriptionLocal { get; set; }
public string ConsumedItemDescriptionEnglish { get; set; }
public string LotCategory1Description { get; set; }
public string LotCategory2Description { get; set; }
public string LotCategory3Description { get; set; }
public string LotCategory1Code { get; set; }
public string LotCategory2Code { get; set; }
public string LotCategory3Code { get; set; }
public string LineCode { get; set; }
public string LineCodeDisplay { get; set; }
public List<Pallet> PalletsProduced { get; set; }
}
My controller gets the above info but my View doesnt need all the above.
For example lets say i get 3 production parameters classes that each one has 20 Pallets. It means that each productionparameter has 20 pallets produced.
I want to show to my MVC View consolidated data for each production parameter.
How i do it correctly?
Standard Case:
Do i create in Models a class with exactly the info i need for the view and then define this class in the #model directive?
AJAX:
What changes if i want to make this via AJAX? My AJAX call will return the consolidated data or the full data and let AngularJS or Jquery make the consolidation on the client?
Standard Case:
Do i create in Models a class with exactly the info i need for the
view and then define this class in the #model directive?
Yes, that's exactly what you should do. You define a view model with only the properties requires by your view. Then your controller action will aggregate one or more domain models into the view model and pass it to the view.
AJAX:
What changes if i want to make this via AJAX? My AJAX call will return
the consolidated data or the full data and let AngularJS or Jquery
make the consolidation on the client?
You should always return a view model from your controller action containing only the required information to the client. This way, not only that you optimize bandwidth and network usage, but you make the life of the clients much easier. They no longer need to make complex data querying and projections but directly use the information that is provided to them under the form of a view model.
Conclusion: your controller actions should always take and pass specifically designed view models from/to views.
You can use ViewModels keeping your business logic separate from Views.A ViewModel represents data that you want to have displayed on your view/page.
Lets say that you have an ProductionParameterclass which contains the following properties:
public class ProductionParameter
{
public string CompanyCode { get; set; }
public string UnitCode { get; set; }
public string ItemDescriptionLocal { get; set; }
public string ItemDescriptionEnglish { get; set; }
public string ConsumedItemDescriptionLocal { get; set; }
public string ConsumedItemDescriptionEnglish { get; set; }
public string LotCategory1Description { get; set; }
public string LotCategory2Description { get; set; }
public string LotCategory3Description { get; set; }
public string LotCategory1Code { get; set; }
public string LotCategory2Code { get; set; }
public string LotCategory3Code { get; set; }
public string LineCode { get; set; }
public string LineCodeDisplay { get; set; }
public List<Pallet> PalletsProduced { get; set; }
}
View models differ from domain models in that view models only contain the data (represented by properties) that you want to use on your view.
Suppose, you want to display only following properties on the view, then your ViewModel can be
public class ProductionParameterViewModel
{
public string CompanyCode { get; set; }
public string UnitCode { get; set; }
public string ItemDescriptionLocal { get; set; }
public string ItemDescriptionEnglish { get; set; }
public string ConsumedItemDescriptionLocal { get; set; }
public string ConsumedItemDescriptionEnglish { get; set; }
public string LineCodeDisplay { get; set; }
public List<Pallet> PalletsProduced { get; set; }
}
Then , on your View, you can use it as below:
#model MyProject.ViewModels.ProductionParameterViewModel
Edit:
If you have two models, then you can put them in a single model as below:
public class ViewModel1
{
}
public class ViewModel2
{
}
public class MyAggregateModel
{
public ViewModel1 Model1 { get; set;}
public ViewModel2 Model2 { get; set;}
}

Newbie view model issue.. to subclass or not to subclass

Ok dead basic question, I'm a self taught developer so often I seem to have gaps where I can't decide which was is the right way... and this is one of them!! Simple I have a view model which has a collection of child items. But where these classes are defined I can't decide if the child object should be a subclass of the parent...
For example this:
public class ActionChartViewModel
{
public IEnumerable<ActionChartItemViewModel> Items { get; set; }
public TextPagingInfo TextPagingInfo { get; set; }
}
public class ActionChartItemViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Rating { get; set; }
public string Comment { get; set; }
public string AssignedToUserName { get; set; }
public string ContactRequested { get; set; }
public bool Resolved { get; set; }
public int NoteCount { get; set; }
public string ContactDetails { get; set; }
public int ResponseId { get; set; }
}
Or this:
public class ActionChartViewModel
{
public IEnumerable<Item> Items { get; set; }
public TextPagingInfo TextPagingInfo { get; set; }
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Rating { get; set; }
public string Comment { get; set; }
public string AssignedToUserName { get; set; }
public string ContactRequested { get; set; }
public bool Resolved { get; set; }
public int NoteCount { get; set; }
public string ContactDetails { get; set; }
public int ResponseId { get; set; }
}
}
I prefer the second one for a code readability and simplicity front, but I don't know the pros and cons of subclasses. What would you guys think??
Thanks in advance!!
I would use separate classes (in same file) as opposed to an inner class. Inner class would be useful when it serves only the parent class, i.e. would not be accessed from outside of the parent class, only by the parent class methods, etc. In your case the inner class needs to be used on view(s), so I don't see a need for it. The first option, i.e. separate classes, is actually simpler to me and reads better.
"SubClass" is when you create more concrete implementations (inherits) of its types. As # bloparod says, you're doing "inner classes". I also rarely use inner classes. Sometimes I use some private or internal classe as a temporary. If you do that, you will need to create with the sintaxe like:
ActionChartViewModel.Item item = new ActionChartViewModel.Item();
I usually separete files and use public classes but sometimes when I have lots and lots of ViewModel, I think a good pratice is to keep all of the same category of ViewModels on a single file and inherited when necessary, for sample:
File: ProductViewModel.cs
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string CategoryName { get; set; }
}
public class ProductDetailViewModel : ProductViewModel
{
public int Stocke { get; set; }
public string Obs { get; set; }
public IEnumerable<ProductMovViewModel> Inventory
/* other properties */
}
public class ProductMovViewModel
{
public int Id { get; set; }
public DateTime Date { get; set;
public int Amout { get; set; }
}
As a good pratice too you can separete in files your ViewModels, as you prefer.

asp.net c# and mongodb models

I wanna know if i can use mongodb like models (model classes) in my project (asp.net mvc 4 c#).
For example:
namespace Demo.Models
{
public class Model1
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
public class MovieDBContext : DbContext
{
public DbSet<Model1> models { get; set; }
}
}
Let's say this is standard model for mssql database. Can i create models like this to use MongoDB collections, documents?
If yes, how? (if you can provide me with link of some examples).
Thanks.
Yes you can don't forget to add BsonId attribute, because every object has to have his own unique id.
public class Model1
{
[BsonId]
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
And example you can find here:
http://www.joe-stevens.com/2011/10/02/a-mongodb-tutorial-using-c-and-asp-net-mvc/
Yes you can use mongodb as model in your project. you just have to define a model class and get the required enetities that you need.But in this you have provide an BsonId attribute for any object for generating a unique id.
here's is a example from my code just check it out.
public class QuestionAttempt
{
public ObjectId QId { get; set; }
public long UserId { get; set; }
[BsonElement("SN")]
public string SkillName { get; set; }
[BsonElement("IC")]
public bool IsCorrect { get; set; }
}
In my code i have given some objects a smaller name with the [BsonElement()] attribute for less memory usage.

Categories