C# API JSON error 500 get in database, Entity Framework - api

I get data from my database, but the swagger throws a 500 error.
This is my code - model of user
public class User
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(30)]
public string Pseudo { get; set; }
[EmailAddress]
public string Mail { get; set; }
[Required]
public string Pwd { get; set; }
[Required]
public bool IsAdmin { get; set; }
public ICollection<Project> UsersProjects { get; set; }
}
DAL code to interact with database:
public TEntity? GetById(params object[] Id)
{
return _Context.Set<TEntity>().Find(Id);
}
public ICollection<Project> GetProjectList(int id)
{
return _Context.projects
.Where(u => u.ProjectManager.Id == id)
.ToList();
}
BLL
public UserBLL GetUser(int id)
{
try
{
UserBLL user = _Repo.GetById(id).ToBLL();
user.UsersProjects = _Repo.GetProjectList(id);
return user;
}
catch
{
throw new Exception("Utilisateur introuvable");
}
}
Controller
public IActionResult GetUser(int id)
{
try
{
return Ok(_userService.GetUser(id));
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
ERROR
Error: response status is 500
When I run the code step by step my object is good nothing is empty so I don't know what is the problem with Swagger
Please help

Related

blazor server (blazorise datagrid) with foreign key column (complex object)

I'm using blazor (blazorise datagrid) with asp.net core and entity framework. I'm facing a problem while trying to perform crud operation on data with
foreign key column (complex object).
Here is my code
Model Classes
public partial class ApproverSequence
{
public int Id { get; set; }
public int? TransactionTypeId { get; set; }
public bool? IsStart { get; set; }
public bool? IsArchived { get; set; }
public virtual TransactionType TransactionType { get; set; }
}
public partial class TransactionType
{
public TransactionType()
{
ApproverSequences = new HashSet<ApproverSequence>();
}
public int Id { get; set; }
public string Description { get; set; }
public bool? IsArchived { get; set; }
public virtual ICollection<ApproverSequence> ApproverSequences { get; set; }
}
Here is my data grid column
<DataGridSelectColumn TItem="ApproverSequence" Field="#nameof(ApproverSequence.TransactionType)" Caption="Description" Editable="true">
<DisplayTemplate>
#{
var transactionTypeDesc = (context as ApproverSequence).TransactionType?.Description;
#transactionTypeDesc
}
</DisplayTemplate>
<EditTemplate>
<Select TValue="int"
SelectedValue="#((int)((TransactionType)(((CellEditContext)context).CellValue)).Id)"
SelectedValueChanged="#( v => ((CellEditContext)context).CellValue = transactionTypes.First(x=> x.Id == v))">
#foreach (var item in transactionTypes)
{
<SelectItem TValue="int" Value="#(item.Id)">#item.Description</SelectItem>
}
</Select>
</EditTemplate>
</DataGridSelectColumn>
#code{
private List<ApproverSequence> approverSequences;
private List<TransactionType> transactionTypes;
protected override async Task OnInitializedAsync()
{
approverSequences = await ApproverSequenceService.GetAll();
transactionTypes = await TransactionTypeService.GetAll();
}
}
Services
public async Task<List<ApproverSequence>> GetAll()
{
try
{
return await _context.ApproverSequences.Include(x=>x.TransactionType).Where(x => x.IsArchived == false).ToListAsync();
}
catch
{
throw;
}
}
public async Task<List<TransactionType>> GetAll()
{
try
{
return await _context.TransactionTypes.Where(x => x.IsArchived == false).ToListAsync();
}
catch
{
throw;
}
}
while running this project it throws System.NullReferenceException: 'Object reference not set to an instance of an object.' exception.
Is there anything I have missed? Thanks in advance

Convert Generic API Response in Blazor

I'm developing a Blazor WASM project and I'm stuck in this point.
I'm using a DataAccess Service to make the requests to EndPoints;
The endpoints return a ResultList, that is a Generic Object that needs to be parsed in Client side. The object definition:
public class ResultList
{
public ResultList(List<object> resultados, string codigoErro = null, string mensagemErro = null)
{
this.Resultados = resultados;
this.CodigoErro = codigoErro;
this.MensagemErro = mensagemErro;
}
public string MensagemErro { get; set; }
public List<object> Resultados { get; set; }
public string CodigoErro { get; set; }
}
In the client side, I receive the same type:
public async Task<ResultList> GetEmpresas()
{
try
{
ResultList Result = await _httpClient.GetFromJsonAsync<ResultList>("api/EmpCadBasico/GetEmpresas");
return Result;
}
catch (Exception ex)
{
return new ResultList(null, null, ex.Message);
}
}
The problem is: I can't convert the List<Object> to other type like List<Empresa>.
The C# compilation doesn't notify bug, but in execution time, it happens.
I tried Serialize and Deserialize, and it doesn't work too:
public async Task GetEmpresas()
{
ResultList Resultado = await _dataAccess.GetEmpresas();
if (await RetornoOk(Resultado))
{
string x = JsonSerializer.Serialize(Resultado.Resultados); // Here, that's fine.
List<Empresa> y = JsonSerializer.Deserialize<List<Empresa>>(x); // Here, it finds the objects, but all of them with null values.
}
}
The X value: '[{"id":1,"nomeEmpresa":"Alamo","cnpj":"00072619000101","dataCadastro":"2020-01-01T00:00:00","colaborador":[],"marca":[]}]'
The Y value: Y value after Deserialization
According to the json return data you provided, I did the following restoration and successfully returned the data, you can refer to it.
Model:
public class TestModel
{
public int id { get; set; }
public string nomeEmpresa { get; set; }
public string cnpj { get; set; }
public string dataCadastro { get; set; }
public List<colaborador> colaborador { get; set; }
public List<marca> marca { get; set; }
}
public class colaborador
{
public int id { get; set; }
public string test { get; set; }
}
public class marca
{
public int id { get; set; }
public string test { get; set; }
}
Then I gave values to individual attributes, and the results are as follows:

How to update an existing entity that has a nested list of entities?

I'm trying to update an entity using entity framework but, everytime I try to do it, it raises an error saying that a nested entity the main class contains cannot be tracked.
These are my classes:
public abstract class BaseEntity
{
public int Id { get; set; }
}
public class Dashboard : BaseEntity
{
public int Order { get; set; }
public string Title { get; set; }
public bool Enabled { get; set; }
public virtual ICollection<Submenu> Submenu { get; set; }
}
public class Submenu : BaseEntity
{
public int Order { get; set; }
public bool Enabled { get; set; }
public string Title { get; set; }
public string Image { get; set; }
public string Descriptions { get; set; }
public virtual ICollection<Action> Actions { get; set; }
public int DashboardId { get; set; }
public virtual Dashboard Dashboard { get; set; }
}
public class Action : BaseEntity
{
public string Type { get; set; }
public string Label { get; set; }
public string Url { get; set; }
public string Extension { get; set; }
public virtual Submenu Submenu { get; set; }
public int SubmenuId { get; set; }
}
The one I am using to update is Dashboard, which contains the rest of the classes.
I'm trying to do it using a generic service layer and a generic repository that are defined this way:
public class GenericService<T> : IGenericService<T> where T : BaseEntity
{
private readonly IBaseRepository<T> baseRepository;
public GenericService(IBaseRepository<T> baseRepository)
{
this.baseRepository = baseRepository;
}
public async Task Update(T entity, T attachedEntity)
{
await baseRepository.Update(entity, attachedEntity);
}
}
public class BaseRepository<T> : IBaseRepository<T> where T : BaseEntity
{
private readonly PortalContext dataContext;
private DbSet<T> DbSet { get; set; }
public BaseRepository(PortalContext context)
{
dataContext = context;
DbSet = dataContext.Set<T>();
}
public async Task Update(T entity, T attachedEntity)
{
dataContext.Entry(attachedEntity).State = EntityState.Detached;
DbSet.Attach(entity);
dataContext.Entry(entity).State = EntityState.Modified;
await dataContext.SaveChangesAsync();
}
}
And, at last but no least, this is the way I am configuring everything at Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<PortalContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("PortalContext"))
);
services.AddTransient(typeof(IGenericService<>), typeof(GenericService<>));
services.AddTransient(typeof(IBaseRepository<>), typeof(BaseRepository<>));
services.AddTransient<Func<string, ClaimsPrincipal, IRoleCheck>>((serviceProvider) =>
{
return (controllerName, claimsPrincipal) =>
new RoleCheck(serviceProvider.GetRequiredService<IGenericService<Dossier>>(),
serviceProvider.GetRequiredService<IGenericService<DossierTemplate>>(),
serviceProvider.GetRequiredService<IGenericService<Dashboard>>(),
controllerName, claimsPrincipal);
});
}
What the application first does is calling the RoleCheck class to retrieve and filter the required entities and, after that, the user can update them.
When I call the update function at the controller
public async Task<ActionResult<Dashboard>> Put(int id, [FromBody] Dashboard dashboard)
{
var currentDashboard = await service.Get(id);
if (currentDashboard == null)
{
return NotFound();
}
await service.Update(dashboard, currentDashboard);
return Ok();
}
I always receive the next error at the repository:
error
Is there something I am doing wrong? I have been stuck with this for a week now...
Thanks in advance and sorry for the long text, but I wanted it to be clear.
I could finally solve it by adding .AsNoTracking() at the Get() method of my repository:
public async Task<T> Get(int id, Func<IQueryable<T>, IIncludableQueryable<T, object>> includes)
{
IQueryable <T> query = DbSet.AsNoTracking();
if (includes != null)
{
query = includes(query);
}
return await query.FirstOrDefaultAsync(m => m.Id == id);
}

How to properly deserialize asp.net core Model State errors to object in xamarin forms

I am having a silly problem trying to deserialize asp.net core model state errors to an object. My code is like this
For backend register method
[HttpPost("register-user")]
[ValidateModel]
public async Task<IActionResult> Index(RegisterDto registerDto)
{
try
{
Data.Models.User user = mapper.Map<RegisterDto, Data.Models.User>(registerDto);
user.LockoutEnd = DateTimeOffset.Now;
user.Warehouse = configuration["Config:Warehouse"];
user.SiteId = Convert.ToInt32(configuration["Config:SiteId"]);
IdentityResult result = await userManager.CreateAsync(user, registerDto.Password);
if (result.Succeeded)
{
AddLogInformation(logger, "User created a new account with password.");
string token = await userManager.GenerateEmailConfirmationTokenAsync(user);
token = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(token));
string confirmationUrl = Url.Action("Index", "EmailConfirmation",
new {userId = user.Id, code = token}, Request.Scheme);
emailSender.SendEmailAsync(registerDto.Email, "Confirm your email",
GetEmailConfirmationTemplate(registerDto.FirstName, registerDto.LastName,
confirmationUrl));
ApplicationRole retailPersonRole =
await roleManager.FindByNameAsync(RoleHelper.GetRetailUserRoleName());
if (retailPersonRole != null) await userManager.AddToRoleAsync(user, retailPersonRole.Name);
if (userManager.Options.SignIn.RequireConfirmedAccount)
{
AddLogInformation(logger, "Sent email confirmation email to user");
return Ok(SuccessResult(null));
}
//If confirm account is set to false
await signInManager.SignInAsync(user, false);
return Ok(SuccessResult(null));
}
// If we got this far, something failed, redisplay form
return Ok(FailedMessage(logger, "Cannot register user at this time. Please try again later."));
}
catch (Exception e)
{
return ServerErrorJsonResult(logger, "Error while trying to register user. Error message is: " + e.Message);
}
}
And I am catching the model state error in action filter and returning a response as below.
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var modelState = context.ModelState;
if (!modelState.IsValid)
context.Result = new BadRequestObjectResult(new JsonResult(new {modelError = true, Errors = modelState}));
}
}
Now in the front-end (xamarin), I have a model to where the error should be deserialised so that I can display a proper error to user.
My register model in the front end is like this
public class RegisterDto: BaseDto
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public string ConfirmPassword { get; set; }
public AddressDto BillingAddress { get; set; }
public RegisterDto Errors { get; set; }
}
My Address Dto is like this
public class AddressDto
{
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string PostCode { get; set; }
public string State { get; set; }
}
I am creating the post request in xamarin like this.
public async Task<TResult> PostAsync<TResult>(string uri, TResult data, string token = "", string header = "")
{
try
{
HttpClient httpClient = CreateHttpClient(token);
if (!string.IsNullOrEmpty(header))
{
AddHeaderParameter(httpClient, header);
}
var content = new StringContent(JsonConvert.SerializeObject(data));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage response = await httpClient.PostAsync(uri, content);
await HandleResponse(response);
string serialized = await response.Content.ReadAsStringAsync();
TResult result = await Task.Run(() =>
JsonConvert.DeserializeObject<TResult>(serialized, serializerSettings));
return result;
}
catch (Exception e)
{
return default;
}
}
And finally, in the view model, I am doing this
--
userToBeRegistered is an instance of RegisterDto
await something.PostAsync(UrlHelper.RegisterUrl, userToBeRegistered);
The serialized string output is like this
{
"errors":{
"Email":[
"Email is required"
],
"LastName":[
"Last name is required"
],
"Password":[
"Password is required"
],
"FirstName":[
"First name is required"
],
"PhoneNumber":[
"Phone number is required"
],
"BillingAddress.City":[
"Suburb is required"
],
"BillingAddress.State":[
"State is required"
],
"BillingAddress.Address1":[
"Street address is required"
],
"BillingAddress.PostCode":[
"Postcode is required"
]
},
"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title":"One or more validation errors occurred.",
"status":400,
"traceId":"|3c2d7d70-49a6eceecbeedab8."
}
My question is how can I deserialise it to an errors object. If I keep running the above code, then I get this error.
"Unexpected character encountered while parsing value: [. Path 'errors.Email', line 1, position 20."
Can anyone help me with this?
Try the below method.
Create ErrorInfor class:
class ErrorInfor
{
public MyError errors { get; set; }
public string type { get; set; }
public string title { get; set; }
public int status { get; set; }
public string traceId { get; set; }
public class MyError
{
public List<string> FirstName { get; set; }
public List<string> LastName { get; set; }
public List<string> PhoneNumber { get; set; }
public List<string> Email { get; set; }
public List<string> Password { get; set; }
[JsonProperty("BillingAddress.City")]
public List<string> Citiy { get; set; }
[JsonProperty("BillingAddress.State")]
public List<string> State { get; set; }
[JsonProperty("BillingAddress.Address1")]
public List<string> Address1 { get; set; }
[JsonProperty("BillingAddress.PostCode")]
public List<string> PostCode { get; set; }
}
}
then you could get the data from your above json string.
ErrorInfor errorInfor = JsonConvert.DeserializeObject<ErrorInfo>(json);

NullObjectReference when performing a PUT in Web Api

I am trying to update a variable inside a class "Conversation" put the parameter objects are not binding for some reason. I don't know why not. As a result I am getting this error:
"Object reference not set to an instance of an object.",
Controller:
[HttpPut]
public async Task<IHttpActionResult> AddMember(string key, User user)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Conversation conver = await db.Conversations.FindAsync(key); //THIS IS NULL
if (conver == null)
{
return NotFound(); //METHOD IS ENDING HERE
}
conver.Members.Add(user); //THIS IS NULL
db.Entry(conver).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
return NotFound();
}
return StatusCode(HttpStatusCode.NoContent);
}
Model class User:
namespace AcademicAssistant.Models
{
[DataContract]
public class User
{
[Key]
[DataMember]
public string Email { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public bool Admin { get; set; }
}
}
Model Class Conversation:
[DataContract]
public class Conversation
{
[Key]
[DataMember]
public string Key { get; set; }
[DataMember]
public string ConversationName { get; set; }
[DataMember]
public string Administrator { get; set; }
[DataMember]
public virtual ICollection<User> Members { get; set; }
[DataMember]
public virtual ICollection<Message> Messages { get; set; }
}
I am testing this in Postman like this:
ROUTE = api/Conversations/AddMember/?key="1LM4"
JSON = {"user": { "Email": "56#56.com", "Password" : "Passw-1", "Admin" : true } }
SOLUTION:
The Route should have been
api/Conversations/AddMember/?key=1LM4
and the JSON formatted like this:
{
"Email": "56#56.com",
"Password" : "Passw-1",
"Admin" : true
}