method within model in MVC - asp.net-mvc-4

I have a model in my MVC app, 'designation'. I have a method getdesig() to simply return all of the designations. I originally had this in my controller but moved to my model recently, with the aim of decluttering my controller and making it thinner. Is this model a logical place to put such a method?
public class designation
{
[Key]
public int DesignationID { get; set; }
public string DesignationName { get; set; }
public virtual ICollection<user> users { get; set; }
private ClaimContext db = new ClaimContext();
public List<designation> getdesig()
{
{
return (from c in db.designations
select c).ToList();
}
}
}

yes, however in more complicated scenarios where conditions exists the controller is the spot to determine "What" needs to be loaded or "how much" needs to be loaded based off the scenario/arguments. In this very simple example it is fine as you are just dumping all the data without regard to any context.
It is a good practice to keep your ViewModels as simple and specific to the View as possible, the ViewModel's job is to simply be a common store to drive the view. The view relies on the model to be set with the appropriate data, it is the job of the controller to determine context and what should be populated in the model.

Related

ASP.NET Core 3.1 Web API: how to protect sensitive data from return with model?

I have a Posts model class that has a relation with Users model.
When I call API to get Posts with the owner of it (user), it returns with all user info including password.
How to prevent model from returning sensitive information like passwords?
You should create new classes that you return from your actions. Only include the fields/information you want to return.
These classes are also known as Data Transfer Objects (DTO).
You can use [JsonIgnore] to avoid serializing the property value:
public class Users
{
public int Id { get; set; }
[System.Text.Json.Serialization.JsonIgnore]
public string Password{ get; set; }
//...
}

Does including Collections in Entities violate what an entity is supposed to be?

I am building a Web API using Dapper for .NET Core and trying to adhere to Clean Architecture principles. The API is consumed by an external Angular front-end.
I have repositories that use Dapper to retrieve data from the database, and this data then passes through a service to be mapped into a DTO for display to the user.
It is my understanding that an entity should be an exact representation of the database object, with no extra properties, and that I should use DTOs if I require some additional properties to show the user (or if I wish to obscure certain properties from the user too).
Suppose I have a DTO:
public class StudentDTO
{
public Guid Id { get; set; }
public string Name { get; set; }
public List<Assignment> Assignments { get; set;}
}
and its corresponding Entity:
public class Student
{
public Guid Id { get; set; }
public string Name { get; set; }
}
With this model, should I want to get a student with all of their assignments, I'd need to have two repository calls, and do something like this in the service:
public StudentDTO GetById(Guid id)
{
var student = this.studentRepository.GetById(id);
var assignments = this.assignmentRepository.GetByStudentId(id);
return SomeMapperClass.Map(student, assignments);
}
But this seems inefficient and unnecessary. My question is, should I not just retrieve the Assignments when I get the student entity in the repository, using a JOIN? Or would this violate what an entity is supposed to be?
I apologise, I do realise this is a rather simple question, but I'd really like to know which method is the best approach, or if they both have their use cases
I think it would be more efficient, since map uses reflections, that is slower tens times
public StudentDTO GetById(Guid id)
{
var student = this.studentRepository.GetById(id);
student.Assignments = this.assignmentRepository.GetByStudentId(id);
return student;
}
but the common way is
return _context.Students.Include(i=>i.Assignments).FirstOrDefault(i=> i.Id==id);
This is why the generic repository is a bad idea in the most casses, since it is hard to guess what set of data you will need.

How does abstractions help in DRY?

When we search "Don't repeat yourself" on Wikipedia, the first sentence is:
In software engineering, don't repeat yourself (DRY) is a principle of
software development aimed at reducing repetition of software
patterns, replacing them with abstractions...
I know that abstractions in software engineering mean hiding implementation complexity of how the behaviors of an API are realized, but it seems that "abstractions" in this sentence is not what I know before. Could someone explain to me what abstraction means here? It would be better if you could give me an example.
I know that abstractions in software engineering mean hiding
implementation complexity of how the behaviors of an API are realized
Yes it means that (absstraction#wikipedia) and very same concept can also be leveraged to reduce repetitions! Or in other words, it can be used to practice DRY.
Let me try to explain that with an example. First I'll show non DRY code (without abstraction), then with use of abstraction I'd try to reduce repetitions.
Let's assume that you wanted to build an email view model based on application form details filled out by applicant and there is an email view class which consumes this emailViewModel to show all non-null details from application form. You could write it like in below example (first attempt)
public class ApplicationForm
{
public AddressDetail AddressDetail { get; set; }
public CustomerDetail CustomerDetail { get; set; }
public ProductDetail ProductDetail { get; set; }
}
public class EmailViewModel
{
public EmailViewModel(ApplicationForm applicationForm)
{
Address = GetAddressDetail(applicationForm.AddressDetail);
Customer = GetCustomerDetail(applicationForm.CustomerDetail);
Product = GetProductDetail(applicationForm.ProductDetail);
}
public string Address { get; set; }
public string Customer { get; set; }
public string Product { get; set; }
}
//view code assume razor view
#if(Model.Address!=null)
{
// method for showing address
}
#if(Model.Customer!=null)
{
// method for showing customer
}
//and other properties
I've kept above code quite simple; only three properties and haven't showed declaration for conversion methods. What if there were 50 properties! In this first approach it would be cumbersome changes that you'd be making in three places. Now I'll show you second example code of how you could create an interface (a way of abstraction) implement DRY.
interface IFormDetail
{
IFormDetailView GetDetail();
}
interface IFormDetailView
{
string ShowView();
}
public class ApplicationForm
{
public List<IFormDetail> FormDetails {get;set;}
}
public class EmailViewModel
{
public EmailViewModel(ApplicationForm applicationForm)
{
if(applicationForm.FormDetails!=null)
{
FormDetails = new List<IFormDetailView>();
foreach(var detail in applicationForm.FormDetails)
{
FormDetails.Add(detail.GetDetail());
}
}
}
public List<IFormDetailView> FormDetails { get; set; }
}
//view code assume razor view
#f(Model.FormDetails!=null)
{
foreach(var detail in Model.FormDetails){
detail.ShowView();
}
}
In this second code example , when you've a new property, you'll only make one change when a new application form property is created.
So while we are hiding complexity of how detail is presented etc., we are also leveraging it to reduce repetition.

MVC view with two different models

I have a view called AccountManager on this view I have a section to update your profile information and update your password.
Both functions require a different model. ManageUserViewModel and ChangePasswordViewModel.
On the AccountManager view, both sections are rendered via #Html.Partial.
When I try to display the page, I receive the following error: "The model item passed into the dictionary is of type 'WebUI.Models.ManageUserViewModel', but this dictionary requires a model item of type 'WebUI.Models.ChangePasswordViewModel'."
How can I render both views without receiving this error?
ViewModel:
public class AccountManagerViewModel
{
public ManageUserViewModel manageUserViewModel { get; set; }
public ChangePasswordViewModel changePasswordViewModel { get; set; }
}
The View:
#model AccountManagerViewModel
/*HTML CODE*/
#Html.RenderPartial("_PartialChangePassword", Model.changePasswordViewModel)
#Html.RenderPartial("_PartialManageUser", Model.manageUserViewModel)
So you just play with the viewModels. Remember that they can have anything you need in the view. Let me know.

loosing dataAnottation when upload model from database

I have a big database existing database to comunicate with, and I'm using EF 5.0 database first, the problem I'm having is that if I create any data decoration like [stringlength(50)] on the class and then the databases is uploaded, when I "upload from database" all data annotations are gone. How can I do to keep them?
It's very simple: You Can't! Because those codes are auto-generated and will be over written on each model update or change.
However you can achieve what you need through extending models. Suppose that EF generated the following entity class for you:
namespace YourSolution
{
using System;
using System.Collections.Generic;
public partial class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int UserID { get; set; }
public virtual UserProfile User{ get; set; }
}
}
and you want do some work arounds to preserve your you data annotations and attributes. So, follow these steps:
First, add two classes some where (wherever you want, but it's better to be in Models) like the following:
namespace YourSolution
{
[MetadataType(typeof(NewsAttribs))]
public partial class News
{
// leave it empty.
}
public class NewsAttribs
{
// Your attribs will come here.
}
}
then add what properties and attributes you want to the second class - NewsAttribs here. :
public class NewsAttrib
{
[Display(Name = "News title")]
[Required(ErrorMessage = "Please enter the news title.")]
public string Title { get; set; }
// and other properties you want...
}
Notes:
1) The namespace of the generated entity class and your classes must be the same - here YourSolution.
2) your first class must be partial and its name must be the same as EF generated class.
Go through this and your attribs never been lost again ...
The accepted answer may work for standard data operations, but I am trying to validate the model prior to the call to DbSet.Add using TryValidateObject. With the accepted answer, it is still not picking up on the data annotations.
What did work for me I found in a .NET Runtime GitHub thread, as proposed by what I'm inferring is one of the .NET developers.
Basically, this is a bug, and you have to force the model to recognize the metadata decorations using TypeDescriptor.AddProviderTransparent . . .
TypeDescriptor.AddProviderTransparent(new AssociatedMetadataTypeTypeDescriptionProvider(typeof(News), typeof(NewsAttrib)), typeof(News));
Once I make this call, TryValidateObject recognizes the data annotations and returns false when any of the constraints are not met.
Here's the link. I little more than half-way down, there's a working code sample in a .zip file.
https://github.com/dotnet/runtime/issues/46678