System.InvalidOperationException ASP.NET C# - c#

Solved Solved Solved
Error;
System.InvalidOperationException: 'An exception was thrown while attempting to evaluate a LINQ query parameter expression. See the inner exception for more information. To show additional information call 'DbContextOptionsBuilder.EnableSensitiveDataLogging'.'
When Is It Happening;
When I try to use register method with those properties, Its poping up on return claims.ToList();:
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string? MiddleName { get; set; }
public string LastName { get; set; }
My Controller Method
[HttpPost("register")]
public IActionResult Register(RegisterDTO registerDTO)
{
var result = _authService.Register(registerDTO, registerDTO.Password);
if (!result.Success) return BadRequest(result);
var createAccessTokenResult = _authService.CreateAccessToken(result.Data);
if (!result.Success) return BadRequest(result);
var createdAccessTokenDataWithSuccessResult = new SuccessDataResult<AccessToken>(createAccessTokenResult.Data, result.Message);
return Ok(createdAccessTokenDataWithSuccessResult);
}
DataAccess Layer
public List<OperationClaim> GetClaims(User user)
{
var claims = from uoc in Context.UserOperationClaims
join oc in Context.OperationClaims
on uoc.OperationClaimId equals oc.Id
where uoc.UserId == user.Id
select new OperationClaim
{ Id = oc.Id, Name = oc.Name };
return claims.ToList();
}
Entity User;
public int Id { get; set; }
public string FirstName { get; set; }
public string? MiddleName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public byte[] PasswordSalt { get; set; }
public byte[] PasswordHash { get; set; }
public bool Status { get; set; }
I solved it
The problem is, Im was not sending parameter user when It is success on Business Layer
public IDataResult<User> Register(RegisterDTO registerDTO, string password)
{
BusinessRules.Run(CheckTheEmailIsAlreadyRegistered(registerDTO));
byte[] passwordHash, passwordSalt;
HashingHelper.CreatePasswordPash(password, out passwordHash, out passwordSalt);
var user = new User()
{
Email = registerDTO.Email,
FirstName = registerDTO.FirstName,
MiddleName = registerDTO.MiddleName,
LastName = registerDTO.LastName,
PasswordHash = passwordHash,
PasswordSalt = passwordSalt,
Status = true
};
var result = _userService.Add(user);
if (!result.Success) return new ErrorDataResult<User>();
return new SuccessDataResult<User>(**user**);
}

Related

ASP.NET Core Web API - How to upload multiple files to specific directory

In ASP.NET Core Web API, I have two models:
public class Employee
{
public Guid Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmployeeCode { get; set; }
public virtual ICollection<EmployeeAttachment> EmployeeAttachments { get; set; }
}
public class EmployeeAttachment
{
public Guid Id { get; set; }
[ForeignKey("EmployeeId")]
public Guid? EmployeeId { get; set; }
public string FileType { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
public virtual Employee Employee { get; set; }
}
An employee will have several attached files. The file will be stored in this directory in the Web API.
Resources -> Attachments
Then I have this DTO.
DTO:
public class EmployeeDetailRequestDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmployeeCode { get; set; }
public Guid? EmployeeId { get; set; }
public string FileType { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
}
BaseResponse:
public class BaseResponse
{
public string ResponseCode { get; set; }
public string ResponseDescription { get; set; }
}
Mapping:
CreateMap<EmployeeDetailRequestDto, Employee>().ReverseMap();
Then eventually put everything into the service.
Service.
Interface:
public interface ICreateEmployeeAsync
{
Task<BaseResponse> CreateEmployeeAsync(EmployeeDetailRequestDto model);
}
public async Task<BaseResponse> CreateEmployeeAsync(EmployeeDetailRequestDto model) : ICreateEmployeeAsync
{
var response = new BaseResponse();
using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
var employee = _mapper.Map<Employees>(model);
employee.FirstName = model.FirstName,
employee.LastName = model.LastName,
employee.EmployeeCoder = model.EmployeeCode
// Insert Employee Data into the DB
_context.Employees.Add(employee);
await _context.SaveChangesAsync();
var folderName = Path.Combine("Resources", "Attachments");
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
foreach (var singleAttachemnt in model)
{
EmployeeAttachment res = new EmployeeAttachment();
res.EmployeeId = employee.Id;
res.FileType = singleAttachemnt.FileType;
res.FileName = singleAttachemnt.FileName;
res.FileName = singleAttachemnt.FilePath;
// Insert Attachment Data into the DB
_context.EmployeeAttachments.Add(res);
await _context.SaveChangesAsync();
}
response.StatusCode = (int)HttpStatusCode.Created;
response.Successful = true;
response.Data = _mapper.Map<BaseResponse>(employee);
response.Message = "Employee created successfully!";
transaction.Complete();
return response;
};
}
Controller:
[HttpPost]
[ProducesResponseType(StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<BaseResponse>> CreateEmployeeAsync([FromBody] EmployeeDetailRequestDto model)
{
var result = await _employeeProfileService.CreateEmployeeAsync(model);
return StatusCode(result.StatusCode, result);
}
I got this error:
Error CS1579 foreach statement cannot operate on variables of type 'EmployeeDetailRequestDto' because 'EmployeeDetailRequestDto' does not contain a public instance or extension definition for 'GetEnumerator'
and model is highlighted in var singleAttachemnt in model
How do I resolve this error, and also save the attachments into the specified folder.
Then, FileName, FileType and FilePath into the DB?
Thanks
In your code, model is of type EmployeeDetailRequestDto which does not have any collections in it. EmployeeDetailRequestDto represents a single attachment for an Employee. It's only in your database entity Employee that you have an Attachments collection.
What you likely want to do is add an EmployeeAttachmentRequestDto collection to your EmployeeDetailRequestDto, and then loop on that.

ASP.NET Core - How to Insert Autogenerated Id from User Model Into Merchant Model

I have these models in ASP.NET Core:
public abstract class EntityBase
{
[Key]
public int Id { get; set; }
}
public class User : EntityBase
{
public string Username { get; set; }
public string Password { get; set; }
public virtual ICollection<Merchant> Merchants { get; set; }
}
public class Merchant : EntityBase
{
public string MerchantName { get; set; }
public string AccountNumber { get; set; }
public int? UserId { get; set; }
[ForeignKey("UserId")]
public virtual User User { get; set; }
public virtual ICollection<Mandate> Mandates { get; set; }
}
ViewModel (DTO):
public class RegisterDto
{
public string MerchantName { get; set; }
[Required(ErrorMessage = "Account Number is required")]
[MaxLength(50)]
public string AccountNumber { get; set; }
[MaxLength(100)]
[Required(ErrorMessage = "Username is required")]
[RegularExpression(#"^\S*$", ErrorMessage = "No white space allowed")]
public string Username { get; set; }
[MaxLength(128)]
[Required(ErrorMessage = "Password is required")]
public string Password { get; set; }
}
EntityMapper:
public class EntityMapper
{
public User FromRegisterDtoToUser(RegisterDto register)
{
User user = new User()
{
Username = register.Username,
Password = register.Password,
};
return user;
}
public Merchant FromRegisterDtoToMerchant(RegisterDto register)
{
Merchant merchant = new Merchant()
{
MerchantName = register.MerchantName,
AccountNumber = register.AccountNumber,
UserId = ?
};
return merchant;
}
}
AuthService:
public async Task<UserDto> register(RegisterDto register)
{
var userExists = await _unitOfWork.UserRepository.GetByUsername(register.Username);
if (userExists != null)
{
throw new Exception("User already exists!");
}
else
{
try
{
register.Password = User.ComputeSha256Hash(register.Password);
var mapper = new EntityMapper();
var user = mapper.FromRegisterDtoToUser(register);
var merchant = mapper.FromRegisterDtoToMerchant(register);
await _unitOfWork.UserRepository.Insert(user);
await _unitOfWork.MerchantRepository.Insert(merchant);
await _unitOfWork.SaveChangesAsync();
if (user != null)
{
var token = GetToken(user);
var map = new EntityMapper();
return map.FromUserToUserDto(user, token);
}
return null;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
}
UserId in Merchant is the Foreign key for Id in User. Id is autogenerated.
Since both User and Merchant Data are inserted at the same time, I want to automatically insert UserId as the Id generated from User in:
Merchant merchant = new Merchant()
{
MerchantName = register.MerchantName,
AccountNumber = register.AccountNumber,
UserId = ...?
};
How do I achive this?
Thanks
I'm not sure what database technology/framework you are using (I'm assuming Entity Framework) but if the UserId is generated upon database insert you will need to save the changes to the database after inserting user and do it again when you insert the merchant.
Basically
await _unitOfWork.UserRepository.Insert(user);
await _unitOfWork.SaveChangesAsync(); // user should have an id now.
merchant.UserId = user.Id;
await _unitOfWork.MerchantRepository.Insert(merchant);
await _unitOfWork.SaveChangesAsync();

Entity Framework and ASP.net MVC - Updating Entity Model with Many-to-Many relationship

Using Asp.Net Identity and Entity Framework, I'am trying to update AspNetUser, and change its AspNetRole.
This is my UserDto class :
public class UserDto : BaseDto
{
public string Uuid { get; set; }
public string Email { get; set; }
public string FullName { get; set; }
public string UserName { get; set; }
public List<RoleDto> Roles { get; set; }
public int NumberOfLikes { get; set; }
public int NumberOfComments { get; set; }
public int NumberOfReviews { get; set; }
}
This is my RoleDto class:
public class RoleDto : BaseDto
{
[ScaffoldColumn(false)]
public string Uuid { get; set; }
[Required(ErrorMessage = "This field is required")]
[MinLength(3, ErrorMessage = "Minimum 3 characters")]
[DisplayName("Role Name")]
public string Name { get; set; }
[ScaffoldColumn(false)]
public int NumberOfUsers { get; set; }
}
This is my Update method in UserController:
[HttpPost]
public ActionResult Edit(UserViewModel vm)
{
UserDto dto = new UserDto
{
Uuid = vm.Uuid,
Email = vm.Email,
FullName = vm.FullName,
UserName = vm.UserName,
Roles = new List<RoleDto>()
};
dto.Roles.Add(new RoleDto
{
Uuid = vm.RoleId
});
OpUserUpdate update = new OpUserUpdate();
update.userDto = dto;
var result = this.Manager.ExecuteOperation(update);
return RedirectToAction("Index");
}
This is User Update Operation:
public class OpUserUpdate : OpUserBase
{
public override OperationResult Execute(FoodRestaurantEntities entities)
{
var id = this.userDto.Roles[0].Uuid;
if (!string.IsNullOrWhiteSpace(this.userDto.Uuid))
{
var user = entities.AspNetUsers.FirstOrDefault(u => u.Id == this.userDto.Uuid);
var role = entities.AspNetRoles.FirstOrDefault(r => r.Id == id);
if(user != null)
{
// If is set email
if (!string.IsNullOrWhiteSpace(this.userDto.Email))
user.Email = this.userDto.Email;
// If is set full name
if (!string.IsNullOrWhiteSpace(this.userDto.FullName))
user.FullName = this.userDto.FullName;
// If is set full name
if (!string.IsNullOrWhiteSpace(this.userDto.UserName))
user.UserName = this.userDto.UserName;
user.AspNetRoles.Add(role);
entities.SaveChanges();
this.Result.Status = true;
this.Result.Message = "Successfully updated";
}
else
{
this.Result.Status = false;
this.Result.Message = "Not successfull";
}
}
return Result;
}
}
1. OperationManager class just executes operation
2. The problem is, that user.AspNetRoles.Add(role) line just adds another Role to a user. For example, if user had User role, it would add Admin role also instead of changing it to Admin. What am I doing wrong?

Angularjs : Post form data with an image to Web API backend

I am trying to post a form data that includes an image from Angularjs client to a Web API backend, but gets an error:
"Could not create an instance of type System.Web.HttpPostedFileBase. Type is an interface or abstract class and cannot be instantiated. Path 'ProfileImage', line 1, position 299."
My angular code is
$scope.RegisterUser = function () {
$http({
method: 'POST',
url: 'http://localhost:2434/api/Account/BrandRegistration/',
data: $scope.brandForm,
file : $scope.brandForm.ProfileImage
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
console.log("libin");
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
My web api method is
public async Task<IHttpActionResult> PostBrandRegistration(BrandRegistration brandVM)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new ApplicationDbContext()));
if (!roleManager.RoleExists("brand"))
{
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
role.Name = "brand";
roleManager.Create(role);
}
if (!roleManager.RoleExists("influencer"))
{
var role = new Microsoft.AspNet.Identity.EntityFramework.IdentityRole();
role.Name = "influencer";
roleManager.Create(role);
}
var user = new ApplicationUser()
{
UserName = brandVM.Email,
Email = brandVM.Email
};
var fileName = "";
var file = HttpContext.Current.Request.Files.Count > 0 ?
HttpContext.Current.Request.Files[0] : null;
if (file != null && file.ContentLength > 0)
{
fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(
HttpContext.Current.Server.MapPath("~/App_Data/ProfileImage"),
fileName
);
file.SaveAs(path);
}
user.BrandUser = new BrandUser()
{
FullName = brandVM.FullName,
ContentType = brandVM.ContentType,
Description = brandVM.Description,
URL = brandVM.URL,
ContactPerson = brandVM.ContactPerson,
Position = brandVM.Position,
PhoneNumber = brandVM.PhoneNumber,
ContactEmail = brandVM.Email,
Address = brandVM.Address,
MarketPlace = brandVM.MarketPlace,
Campaigns = brandVM.Campaigns,
InfluencerRating = brandVM.InfluencerRating,
ProfileImage = fileName
};
user.BankDetail = new BankDetail()
{
AccountNumber = brandVM.AccountNumber,
AccountName = brandVM.AccountNumber,
IRD = brandVM.IRD,
GST = brandVM.GST
};
IdentityResult result = await UserManager.CreateAsync(user, brandVM.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
else
{
await this.UserManager.AddToRoleAsync(user.Id, "brand");
return Ok();
}
}
And my View Model is
public class BrandRegistration
{
public string Email { get; set; }
public string Password { get; set; }
public string PasswordConfirmation { get; set; }
public string FullName { get; set; }
public string ContentType { get; set; }
public HttpPostedFileBase ProfileImage { get; set; }
public string Description { get; set; }
public string URL { get; set; }
public string ContactPerson { get; set; }
public string Position { get; set; }
public string Company { get; set; }
public int PhoneNumber { get; set; }
public string ContactEmail { get; set; }
public string Address { get; set; }
public string AccountNumber { get; set; }
public string AccountName { get; set; }
public string IRD { get; set; }
public string GST { get; set; }
public bool MarketPlace { get; set; }
public bool Terms { get; set; }
public double InfluencerRating { get; set; }
public int Campaigns { get; set; }
}
I really appreciate if someone can advice me of where i have gone wrong.
I'm not familiar with .NET, but you definitely should use form data on the client side.
var fd = new FormData();
fd.append('file', $scope.brandForm.ProfileImage);
fd.append('data', $scope.brandForm)
$http({
method: 'POST',
url: 'http://localhost:2434/api/Account/BrandRegistration/',
data: fd
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})

LINQ Entity Framework Value cannot be null. Parameter name: String

I'm trying to return a collection of view-model objects to my view, from my Entity data-model and get the following error:
Value cannot be null.
Parameter name: String
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentNullException: Value cannot be null.
Parameter name: String
Source Error:
Line 22: {
Line 23: IEnumerable<CollegeContactViewModel> contacts = db.CollegeContacts.Where(cc => cc.CollegeContactID >0).AsEnumerable().ToList()
Line 24: .Select(c => new CollegeContactViewModel()
Line 25: {
Line 26: Id = c.CollegeContactID,
Here is my index action
public ActionResult Index()
{
IEnumerable<CollegeContactViewModel> contacts = db.CollegeContacts.AsEnumerable().ToList()
.Select(c => new CollegeContactViewModel()
{
Id = c.CollegeContactID,
Status = c.CollegeContStatus,
Center = c.CollegeContCenter,
Salutation = c.CollegeContSalutation,
FirstName = c.CollegeContFname,
LastName = c.CollegeContLname,
Position = c.CollegeContPosition,
Department = c.CollegeContDept,
Institution = c.CollegeContInstitution,
Address = new Address()
{
AddressLine1 = c.CollegeContAdd1,
AddressLine2 = c.CollegeContAdd2,
City = c.CollegeContCity,
State = c.CollegeContSt,
PostalCode = c.CollegeContZip
},
Email = c.CollegeContEmail,
Phone = c.CollegeContPhone,
Opt = c.CollegeContOpt,
ContactDate = c.CollegeContDate,
OnMailingList = c.CollegeContMailListSingle,
NumberOfCatalogsSent = int.Parse(c.NumCatalogsSent),
DateSent = c.Datesent.ToString(),
DateEntered = c.DateEntered.ToString(),
Reception = c.Reception,
Partner = c.Partner,
Website = c.SAwebsite,
Poster = c.CollegeContPoster
});
return View(contacts.ToList());
}
The CollegeContactViewModel
public class CollegeContactViewModel
{
public int Id { get; set; }
public string Status { get; set; }
public string Center { get; set; }
public string Salutation { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Position { get; set; }
public string Department { get; set; }
public string Institution { get; set; }
public Address Address { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Opt { get; set; }
public string ContactDate { get; set; }
public bool? OnMailingList { get; set; }
public int NumberOfCatalogsSent { get; set; }
public string DateSent { get; set; }
public string DateEntered { get; set; }
public string Reception { get; set; }
public string Partner { get; set; }
public string Website { get; set; }
public string Poster { get; set; }
}
I have the exact same type of code for another entity in my database and it works just fine. Also all the fields, with the exception of the primary key, allow null, so that can't be it. I've also stepped through the code and the Id is getting populated.
Can somebody please tell me why I keep getting this exception?
Scanning your code for a string parameter, this looks like the most likely (only?) candidate:
NumberOfCatalogsSent = int.Parse(c.NumCatalogsSent),
If c.NumCatalogsSent is null, that is the error you'd get.
I'd try this instead (EF v4 can translate the null-coalescing operator):
NumberOfCatalogsSent = int.Parse(c.NumCatalogsSent ?? "0"),

Categories

Resources