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

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; }
//...
}

Related

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.

return multiple objects using Web Api 2

I have get method, which should return users and there permissions. I have a users object and a permissions object, which i populate like this:
List<Users> users= MtFacade.GetUser(query);
List<UserPermissions> upermissions = MtFacade.GetUserPermission(User.Identity.Name);
My API controller returns a HttpResponse, for which I need to send back two lots of JSON, using the two objects.
I can do this if i return just one at a time, but how do i combined the two?
Wrap them in a class that encompasses properties of their types.
I'm sure you've already figured this out since you've accepted the answer, but in case it helps you or others that see this question here is a code example:
// this would be your class that can encompass the two objects
public class UsersAndPermissions
{
public List<User> Users { get; set; }
public List<UserPermissions> Permissions { get; set; }
}
In your web api method use the above class like this
var usersAndPerms = new UsersAndPermissions
{
Users = MtFacade.GetUser(query),
Permissions = MtFacade.GetUserPermission(User.Identity.Name)
};
// now your json that you return from the web api has both of the objects data
return usersAndPerms;

method within model in MVC

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.

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

ASP.NET MVC Web Api Get Not Mapping QueryString To Strongly Typed Parameter

The parameter request is always null using Web API. Am I missing something with using a strongly typed object as a parameter instead of simple types as the parameters.
Url
http://localhost:2222/api/v1/divisions?EventId=30
Controller Action
public virtual ApiDivisionsResponse Get(ApiDivisionsRequest request)
{
return _apiDivisionsService.GetDivisions(request);
}
Object
public class ApiDivisionsRequest : ApiAuthorizedRequest
{
public ApiDivisionsRequest()
{
Page = 1;
PageSize = 10;
}
public int EventId { get; set; }
public int PageSize { get; set; }
public int Page { get; set; }
public string[] Includes { get; set; }
}
I very strongly invite you to read the following article to better understand how parameter binding works in the Web API. After reading it you will understand that by default the Web API binds query string parameters to primitive types and request body content to complex types.
So if you need to bind query string parameters to complex types you will need to override this default behavior by decorating your parameter with the [FromUri] parameter:
public virtual ApiDivisionsResponse Get([FromUri] ApiDivisionsRequest request)
{
...
}
And yeah, I agree with you - that's a hell of a mess - model binding was so easy in plain ASP.NET MVC and they created a nightmare in the Web API. But once you know how it works you will avoid the gotchas.