i am trying te sent an object in JSON format but the method always get a null object
here is the ERROR :
Server Error in '/' Application.
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
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.Data.Entity.Validation.DbEntityValidationException: Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
Source Error:
Line 15: context = ApplicationDbContext.Create();
Line 16: context.Users.Add(user);
Line 17: if (context.SaveChanges() == 0)
Line 18: {
Line 19: context.Dispose();
Source File: D:\Education\Git\Online-Store-Platform-API\OnlineStorePlatform\OnlineStorePlatform\DBContext\UserContext.cs Line: 17
and that is my code :
public class AccountController : Controller
{
//public UserDTO user;
public UserContext myContext;
// GET: Account
public ActionResult Index()
{
return View();
}
//[HttpPost]
public ActionResult Register([FromBody]UserDTO user)
{
//user = new UserDTO(email, password, userName);
myContext = new UserContext();
if (myContext.addUser(new User(user)) == null) return Content("ERROR");
return Content("Created Successfully");
}
}
when ever i sent an UserDTO object always get null
my request :
UseDTO class:
public class UserDTO
{
public String email, userName, password;
public UserDTO(String email, String password, String userName)
{
this.email = email;
this.password = password;
this.userName = userName;
}
public UserDTO() { }
}
when i try debugging i got a null object
Convert email, username and password to property.
public string Email { get; set;}
public class AccountController : Controller
{
public UserContext myContext;
public AccountController () : this(new UserContext()) {}
public AccountController (UserContext _myContext)
{
myContext = _myContext;
}
// GET: Account
public ActionResult Index()
{
return View();
}
public ActionResult Register(UserDTO user)
{
if (ModelState.IsValid) {
myContext.Add(User);
//ToDo: Redirect or many options
}
return View(user);
}
}
Edit:
This is important
public class UserDTO
{
public String email { get; set; }
public String userName { get; set; }
public String password { get; set; }
}
Ok i found the solution to my problem..
the problem is that i am inherting from class Controller but i should inhert from ApiController .
public class AccountController : Controller
{
........
}
it worked after that.. thank you all
Related
ModelState.IsValid returns false even if the properties with Required annotation have valid values. I logged the string representation of the object and it shows that the Username and Password is not empty.
User Model
public class User
{
public int Id { get; set; }
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
public override string ToString()
{
return $"Username: {Username}, Password: {Password}";
}
}
Controller
public class AuthController : Controller
{
private readonly UserContext _context;
private readonly ILogger<User> _logger;
[BindProperty]
public User AuthUser { get; set; }
public AuthController(ILogger<User> logger, UserContext context)
{
_logger = logger;
_context = context;
}
public IActionResult Login()
{
return View(new User());
}
[HttpPost]
public async Task<IActionResult> Login(string returnURL = null)
{
if (!ModelState.IsValid)
{
_logger.LogInformation(AuthUser.ToString());
//Executes this block even if Username and Password has data
}
}
public IActionResult Login()
{
return View(new User());
}
[HttpPost]
public async Task<IActionResult> Login(User model,string returnURL = null)
{
if (ModelState.IsValid)
{
_logger.LogInformation(model.ToString());
}
return View(model);
}
I had the same problem for a long time and finally I found it. In my case, it was the Id field :)
Just place a breakpoint and check your ModelState in runtime and go to this section :
ModelState -> Root -> Children
and you will see all valid and invalid Keys
There may be issues with int fields.
In your case, that could be the Id field.
As we know, integer can not be null and if in view page we have set its value to empty, it will be marked as invalid in the ModelState in the post method. Because, int can not be null/empty.
I am using ASP.NET Core 5.0 and I have Users Controller with Register method, which receives UserRegisterInputModel. The problem is that all responses from my API are in specific format, but the ApiController auto-validates the input model and returns BadResponse in another format.
This is my abstract response model
public abstract class ResponseModel
{
public ResponseModel(bool successfull, int statusCode)
{
this.Successfull = successfull;
this.StatusCode = statusCode;
this.ErrorMessages = new List<string>();
}
public bool Successfull { get; set; }
public int StatusCode { get; set; }
public List<string> ErrorMessages { get; set; }
public object Data { get; set; }
}
And this is my BadResponseModel
public class BadResponseModel : ResponseModel
{
public BadResponseModel()
: base(false, 400)
{
}
}
This is part of my Register method in Users Controller.
[HttpPost]
public async Task<IActionResult> Register(UserRegisterInputModel input)
{
if (!ModelState.IsValid)
{
return Json(new BadResponseModel()
{
ErrorMessages = new List<string>()
{
"Invalid register information"
}
});
}
ApiController functionality auto-validates my model and the return statement for BadResponseModel is never reached. Is there any way of stopping auto-validation or changing the default response from ApiController validation ?
You can disable automatic model state validation by using "ApiBehaviourOptions.SuppressModelStateInvalidFilter" property:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.apibehavioroptions.suppressmodelstateinvalidfilter?view=aspnetcore-5.0
So a very basic example of usage would be like that (ConfigureServices method in Startup.cs):
services.Configure<ApiBehaviorOptions>(opt => { opt.SuppressModelStateInvalidFilter = true; });
I wish to implement OWIN as per the example I could find here:
http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api
However, since this way of working is new to me especially using my self created database I would like some guidance.
I can submit my registration request without a problem.
The post takes me to the AccountController:
[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try {
var email = model.Email;
var password = model.Password;
var user = new users() {
Email = email,
PasswordHash = password,
Password = password
};
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
}
catch(Exception ex)
{
throw;
}
}
This triggers the below code:
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
ApplicationUserManager:
public class ApplicationUserManager : UserManager<users>
{
public ApplicationUserManager(IUserStore<users> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<users>(context.Get<DaumAuctionEntities>()));
var dataProtectionProvider = options.DataProtectionProvider;
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = true,
RequireUppercase = true,
};
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<users>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
But for some weird reason I'm getting
modelState: {undefined: ["Name cannot be null or empty."]}
Even though I don't use name anywhere?! Where is this name coming from?
So I presume I'm doing something wrong but it's hard to debug without a clear explanation on how to implement OWIN with an existing DB.
Below my context/entity and users table that I would like to use to store me user data.
context:
public partial class DaumAuctionEntities : IdentityDbContext<users>
{
public DaumAuctionEntities()
: base("name=DaumAuctionEntities")
{
}
public DbSet<addresses> addresses { get; set; }
public DbSet<auctions> auctions { get; set; }
public DbSet<images> images { get; set; }
public DbSet<users> users { get; set; }
}
users : IdentityUser:
public partial class users : IdentityUser
{
public override string UserName
{
get
{
return Email;
}
set
{
Email = value;
}
}
override public string PasswordHash
{
get
{
return Password;
}
set
{
Password = value;
}
}
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<users> manager, string authenticationType)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
}
public partial class users
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public System.DateTime CreatedDate { get; set; }
public Nullable<System.DateTime> ModifiedDate { get; set; }
}
Edit:
If I add UserName back to my new users object before I try to call CreateAsync, the error is gone but I get another one instead:
"The specified type member 'UserName' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."
Edit II:
I also have this issue in the tutorial code! This is just a freaking bug in .NET?
Edit III
I tried to do an override as you can see in the partial class Users above. But I still have the same error.
The issue is due to the fact that I did not add UserName to my new user before I call UserManager.CreateAsync. If I add the UserName I have the exact same issue as this: MVC 5 IdentityDbContext and DbContext transactions
That issue seems to point to the fact that ASP.NET Identity is using the UserName property in a query, but Entity Framework compains that the property is not mapped to a database column in your Entity model (EDML).
I don't see many problems with your code
Remove the users DbSet from your DaumAuctionEntities class (See this)
Remove the Id property from your users class
Set the CreatedDate property when you create a new users inside the Register
method
Then you should be OK
Also,about:
Nope, it actually passes that. It comes from I believe the manager but
whenever I try to debug that code the debugger states that it jumped
over it (most likely due to the fact that it's an external library
from Microsoft).
If you wrap the call with a try/catch you'll be able to see the error message
I got few issues with the code you have shared here but not exactly the same as you mentioned. I have shared the example on git for your reference. Try it by your self and let me know if you see any issues.
Git URL - https://github.com/JitJDN/OWINStack
See, code is still the same as yours:
var email = model.Email;
var password = model.Password;
var user = new users()
{
Email = email,
PasswordHash = password,
Password = password
};
IdentityResult result = await UserManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
{
return GetErrorResult(result);
}
return Ok();
I finally got it working.
In the end I had to add adjust the partial class Users (which is a table in my SQL database) so that UserName and Password override the fields of IDentityUser (so not like I did in my question):
public partial class users
{
public int Id { get; set; }
public string UserName {get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? CreatedDate { get; set; }
public DateTime? ModifiedDate { get; set; }
}
I then just had to pass the password and UserName when I created the user:
var user = new users() {
Email = email,
UserName = email,
PasswordHash = password,
Password = password
};
While checking whether the user exists in the database, this happens "The entity type User is not part of the model for the current context".
"Sorry for my bad english"
This my Context:
public class UserContext : DbContext
{
public UserContext() :
base("PracticeDB")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PracticeDB>().ToTable("Users");
}
public DbSet<User> Users { get; set; }
}
View model:
namespace Models.Models
{
public class LoginModel
{
[Required]
public string Name { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}
Controller:
namespace Models.Controllers
{
public class AccountController : Controller
{
public ActionResult Login()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
User user = null;
using (UserContext db = new UserContext())
{
user = db.Users.FirstOrDefault(u => u.Name == model.Name && u.Password == model.Password);
}
if (user != null)
{
FormsAuthentication.SetAuthCookie(model.Name, true);
return RedirectToAction("Users");
}
else
{
ModelState.AddModelError("", "Пользователя с таким логином и паролем нет");
}
}
return View(model);
}
}
}
enter image description here
I think this line in your UserContext:
modelBuilder.Entity<PracticeDB>().ToTable("Users");
Needs to change to:
modelBuilder.Entity<User>().ToTable("Users");
You need to tell the DbContext about the User model in OnModelCreating. Try changing the PracticeDB model to User in modelBuilder.Entity<PracticeDB>().ToTable("Users");.
I am developing an ASP .Net MVC 3 application using C# and SQL Server 2005.
I've created 2 models (User & Poste) with their controllers (UserController & PosteController) thanks to the method of creation with 'Read/Write actions and views, using Entity Framework'.
Everything goes well for the Poste, I can create, edit, delete...
The problem is related to the User. In fact, when I put /User in my URL to access to the index, this error appears to me :
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.Data.SqlClient.SqlException: Nom d'objet
'dbo.Users' non valide.
This is User model code :
public class User
{
[Required]
[Key]
[Display(Name = "Matricule :")]
public string Matricule { get; set; }
[Required]
[Display(Name = "Nom :")]
public string Nom_User { get; set; }
[Required]
[StringLength(100, ErrorMessage = "Le {0} doit avoir au minimum {2} caractères.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Mot de passe :")]
public string passWord { get; set; }
[Required]
[Display(Name = "Type :")]
public string Type_User { get; set; }
[Required]
[Display(Name = "ID_UF :")]
public string ID_UF { get; set; }
}
public class GammeDBContext : DbContext
{
public DbSet<User> Users { get; set; }
}
and this is the UserController code :
public class UserController : Controller
{
private GammeDBContext db = new GammeDBContext();
//
// GET: /User/
public ViewResult Index()
{
return View(db.Users.ToList());
}
//
// GET: /User/Details/5
public ViewResult Details(string id)
{
User user = db.Users.Find(id);
return View(user);
}
//
// GET: /User/Create
public ActionResult Create()
{
return View();
}
//
// POST: /User/Create
[HttpPost]
public ActionResult Create(User user)
{
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
//
// GET: /User/Edit/5
public ActionResult Edit(string id)
{
User user = db.Users.Find(id);
return View(user);
}
//
// POST: /User/Edit/5
[HttpPost]
public ActionResult Edit(User user)
{
if (ModelState.IsValid)
{
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
//
// GET: /User/Delete/5
public ActionResult Delete(string id)
{
User user = db.Users.Find(id);
return View(user);
}
//
// POST: /User/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(string id)
{
User user = db.Users.Find(id);
db.Users.Remove(user);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
and this is what I added in my web.config file :
<add name="GammeDBContext"
connectionString="Data Source=SWEET-DE396641E\SQLEXPRESS;database=Flux; Integrated Security=true"
providerName="System.Data.SqlClient" />
<add name="GammeDBContextP"
connectionString="Data Source=SWEET-DE396641E\SQLEXPRESS;database=Flux; Integrated Security=true"
providerName="System.Data.SqlClient" />
PS :
GammeDBContext is for the 'User'
GammeDBContextP is for the 'Poste'
So is there any solution ?
is your database table called 'User'? If it is, try throwing this code in with your context class.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
}
This bugged the bajeezus out of me one time.
Also why do you have 2 identical connection strings?