How to edit validation on Models generated by EF from a database? - asp.net-mvc

I have a database with a table users. I generate the EF .edmx from the database and I can then access the users via:
public ActionResult Index()
{
var obj = context.Users.ToList();
return View(obj);
}
Which is fine my problem is that when I do the edit:
public ActionResult Edit(Guid id)
{
var obj = context.Users.Where(c => c.UserId == id).SingleOrDefault();
return View(obj);
}
I have no idea how to access the User model to add validation message? I was hoping to see something like:
public class User
{
[Required]
[Display(Name = "username")]
public string UserName { get; set; }
{
But I don't and I'm novice and don't really understand how to access / edit this model when generate from a database. Any advice tutorials would be appreciated.

see if u were using code first u could have used what user MISHA has suggested, u r using database first (as u are generating edmx from DB). In this case for mvc-validation to hook automatically- you have provide model's metadata.
You can create a metadata as below
namespace Your_Models_NameSpace
{
[MetadataType(typeof(UserMetaData))]
public partial class User
{
public class UserMetaData
{
[DisplayName("User Name")]
[Required(ErrorMessage = "Please provide a valid username")]
public object UserName { get; set; }
}
}
}

What you can do is, in the same namespace as your model, create a partial class with metadata like so:
[MetadataType(typeof(IPConfigMetadata))]
public partial class IPConfig
{
internal sealed class IPConfigMetadata
{
private IPConfigMetadata() { }
[RegularExpression(#"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b", ErrorMessage = "Must be a valid IP Address")]
public string CommanderIP { get; set; }
[Range(1024, 65535)]
public int IPPort { get; set; }
}
}

Check this post.
You could do something like:
public class User
{
[Required(ErrorMessage = "Username is required")]
public string UserName { get; set; }
{
Then in your action you would do:
public ActionResult Edit(User user)
{
if(ModelState.IsValid)
{
// Save user
}
return View(user);
}

Related

Model binding Asp net core 2.2

I have the following complex model:
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public int UserId { get; set; }
}
I need to bind the whole model in my action method using [FromBody], while Id property should come [FromQuery]. My action method looks like this:
public IActionResult Delete([FromBody]User userRequest)
{
// Some code
}
The thing is that I can't change the model, because it is 3-rd party and also, I can't have Id as the second parameter in action method, because I have validation logic for userRequest where I need the Id. Any ideas?
Use a DTO/view model and map over to User. For example:
public class UserDTO
{
public string UserName { get; set; }
public int UserId { get; set; }
}
Then:
public IActionResult Delete(int id, [FromBody]UserDTO userRequest)
{
var user = new User
{
Id = id,
UserName = userRequest.UserName,
UserId = userRequest.UserId
}
// do something
}

how to save and update a record in the same form using mvc viewmodel

public int ID { get; set; }
[Required]
public string Surname{get;set;}
[Required (ErrorMessage="FirstName Required")]
public string Firstname{get;set;}
[Required(ErrorMessage="please enter your OtherNames")]
public string Othername{get;set;}
[Required(ErrorMessage="please enter your sex")]
public string Sex{get;set;}
[Required (ErrorMessage="please enter your DateOfBirth")]
public DateTime DateOfBirth{get;set;}
[Required(ErrorMessage="Address is required")]
public string Address{get;set;}
[Required(ErrorMessage="city is required")]
public string City{get;set;}
[Required(ErrorMessage="State is required")]
public string State{get;set;}
public string Country{get;set;}
}
i have created an interface which acts as the middleman between my Domain Layer and my WEBUI
public interface IStudentRepository
{
IQueryable<Student> Student { get; }
//we using a method to save the record into our database
void Save(Student student);
}
the interface is being implented by my repository class which perfoms all the actions of saving the records into the database and retrieving it..
public class EFRepository:IStudentRepository
{
private EFDBContext context = new EFDBContext();
public IQueryable<Student> Student{ get { return context.Students; } }
public void Save(Student student)
{
if (student.ID == 0)
{
context.Students.Add(student);
}
context.SaveChanges();
}
and then i have a view which creates an instance of the student class and uses the interface to store the records in the database, which works perfectly..
[HttpPost]
public ActionResult Registration(Student student)
{
if (ModelState.IsValid)
{
studentrepository.Save(student);
}
return View(student);
}
this works perfectly for me..
But i want to be able to update this same fields incase the student make changes to the fields and it should overwrite the existing record in the database.
i have seen my tutorials where the student id number is passed as an action link before it overwrites the existing record.
however,what i want is the ability for the student to edit the same form using the same button and the same view being display.any help would be appreciated.
You just need to change you repository method to look something like this:
public class EFRepository:IStudentRepository
{
private EFDBContext context = new EFDBContext();
public IQueryable<Student> Student{ get { return context.Students; } }
public void Save(Student student)
{
if (student.ID == 0)
{
context.Students.Add(student);
}
else
{
Student existingStudent = context.Students.FirstOrDefault(x => x.ID == student.ID);
if(existingStudent != null)
{
context.Entry(existingStudent).CurrentValues.SetValues(student);
context.Entry(existingStudent).State = System.Data.Entity.EntityState.Modified;
}
}
context.SaveChanges();
}
or you can use the Entity Framework Attach method as this will automatically track the object state and update the details

Add New Controller to MVC 4

I want to add new controller to my MVC application.Here is my screen
First of all MovieDBContext do not exist in this list,
I created New one. When i press Add button,I get this popup error
Do i need to create Model first? Here is my Model code
`public class LogOn
{
Database db = DatabaseFactory.CreateDatabase("MovieDBContext");
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}`
My web.config has this code
<add name="MovieDBContext" connectionString="Data Source=.\SQLExpress;Initial Catalog=test;User ID = sa; Password = 123456;"
providerName="System.Data.SqlClient" />
I think you should do this:
public class LogOn
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}
public class LogOnContext : DbContext
{
public LogOnContext() : base("MovieDBContext")
{
}
public DbSet<LogOn> LogOns{ get; set; }
}
Then build project and add a scaffolding item (controller).
You need to change because there's an ambiguous reference:
replace in Edit() method (after controller scaffolding):
db.Entry(logon).State = EntityState.Modified;
with:
db.Entry(logon).State = System.Data.Entity.EntityState.Modified;
Your Edit method should look like as follows:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="Id,UserName,Password")] LogOn logon)
{
if (ModelState.IsValid)
{
db.Entry(logon).State = System.Data.Entity.EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(logon);
}
After you create the model as follows:
public class LogOn
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
}
public class LogOnContext : DbContext
{
public LogOnContext()
: base("MovieDBContext")
{
}
public DbSet<LogOn> LogOns { get; set; }
}
and buil project when you select Data Context class you select (in scaffolding menu)
LogOnContext (MvcFirst.Models) not MvcFirst.Models.DBContext
I had the same problem. I used entity framework version 6. Then I found that it was happening for EF. Because version 6 does not support scaffolding properly with MVC 4. Then I remove it and replace it with version 5. This tricks may be help you. If it helps please give a vote. Thanks

ASP.NET MVC - create a new Model or use a Entity framework class

I am developing a ASP.NET MVC 3 application, i am using entity framework code first in order to create the classes of my app, and i also have a repository in order to perform the operations on it, keeping clean the DBContext and the DBEntities definitions.
My doubt is about the render of the views and the way where a edit model is saved.
If I have this entity that represent a user stored in my DB:
//Entity:
public class User
{
[Key]
public int IdUser { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
And i want to show a View with the FirstName, LastName, Email and NewPassword, ConfirmPasword and CurrentPassword, in order to let the user change his data, typing the CurrentPassword to confirm the changes, so my doubt is, fieds like ConfirmPasword and CurrentPassword aren´t in my entity so i need to create a new model for this View and the copy the information that i want from my new Model to my database entity in order to save it? Like:
public class UpdateUserModel
{
[Required]
[Display(Name = "Name")]
public string FirstName{ get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName{ get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Not valid email")]
public string Email { get; set; }
[DataType(DataType.Password)]
[Display(Name = "New password")]
public string NewPasword{ get; set; }
[DataType(DataType.Password)]
[Display(Name = "Confirm the New Pasword")]
[Compare("NewPasword", ErrorMessage = "Password doesn´t mach.")]
public string ConfirmPasword{ get; set; }
[Required(ErrorMessage = "Need to specify the current password to save changes")]
[DataType(DataType.Password)]
[Display(Name = "Current Password")]
public string CurrentPassword { get; set; }
}
and in the controller i made:
public ActionResult UpdateUser(UpdateUserModel model)
{
User u = (User)Membership.GetUser();
u.FirstName = model.FirstName;
u.LastName = model.LastName;
u.Email = model.Email;
if (!String.IsNullOrEmpty(model.NewPassword))
{
u.Password = FormsAuthentication.HashPasswordForStoringInConfigFile(model.NewPassword.Trim(), "md5");
}
repository.UpdateUser(u);
return View();
}
There are any way of doing this having a controller like:
public ActionResult UpdateUser(User u)
{
repository.UpdateUser(u);
return View();
}
Because if i have that, how i can add the field like, ConfirmPassword or CurrentPassword in order to made the validation for this specific View.
If I were you, I wouldn't use domain model in my presentation layer. I would create a view model (another class) which will be very similar to my domain model. I would then use auto-mapping tool to map from my domain model to the view model.
This is a very common scenario, so if you Google for "view and domain" models you should find everything you need.
public class User {
[Key]
public int IdUser { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
public class UpdateUserViewModel {
// Original fields
public string Password { get; set; }
public string PasswordConfirmation { get; set;
}
You could then configure auto-mapper to remove your boiler plate code:
public ActionResult ShowUser()
{
var domainModel = new User(); // I'm assuming that properties are set somewhere
var viewModel = new UserViewModel();
Autommaper.Map(domainModel, viewModel);
return View(viewModel);
}
This is very rough, but hopefully you get an idea.
Update 1: **
As i understood is better to create a new model for each view and then map it into the entity
It's not just better, it provides better separation of concerns, makes your code easily testable. Just by looking at the name of the class, I can see its purpose UpdateUserViewModel, RegisterUserViewModel etc).
Original fields, in this class is supposed to be the Metadata with the validation and that stuff isn't?
By original fields I mean:
public class UserViewModel{
public string UserName { get; set; }
public string FirstName { get; set; }
}
These fields are already in your User class, so I saved my time by not typing them in again.
This will be change my model from MVC to MVVM or not beacuse i still have a controller?
I believe what I've suggested is still an MVC pattern, rather than MVVM.
About the Automaper, are you using github.com/AutoMapper/AutoMapper?
Automapper is something that I have used. There are few tools out there and they do pretty much the same thing. Try out few and find one that suits your requirements the most.
Good luck.
Usually I use areas for different parts of my project, as an aside of where to put this extra code.
Pretty much you are going to add to your model folder a viewmodel.cs class. Inside this class will hold your definitions for how the data will be modelled in the view. These viewmodels will reflect the parts of the entity you wish the user to interact with. The interaction will be done in the controllers via [HttpGet] where you pass in the view model to be interacted with, and [HttpPost] where you send the model back and then map it to an entity.
ViewModels.cs:
public class UserViewModel
{
public string UserName { get; set; }
}
SomeController:
public ActionResult getView()
{
var uvm = new UserViewModel();
return View(uvm);
}
View getView.cshtml:
#model project.namespace.UserViewModel
#using (Html.BeginForm())
{
#Html.EditorFor(m => m.UserName)
<input type="submit" value="New User Name" />
}
Back in controller:
[HttpPost]
public ActionResult getView(UserViewModel model)
{
var entity = new ActualEntity();
entity.username = model.UserName;
//more mapping
//commit changes somewhere
return RedirectToAction("getView");
}

Disable validation on certain fields

I've got a ViewModel for adding a user with properties: Email, Password, ConfirmPassword with Required attribute on all properties. When editing a user I want the Password and ConfirmPassword properties not to be required.
Is there a way to disable validation for certain properties in different controller actions, or is it just best to create a seperate EditViewModel?
I like to break it down and make a base model with all the common data and inhierit for each view:
class UserBaseModel
{
int ID { get; set; }
[Required]
string Name { get; set; }
[Required]
string Email { get; set; }
// etc...
}
class UserNewModel : UserBaseModel
{
[Required]
string Password { get; set; }
[Required]
string ConfirmPassword { get; set; }
}
class UserEditModel : UserBaseModel
{
string Password { get; set; }
string ConfirmPassword { get; set; }
}
Interested to know if there is a better way as well although this way seems very clean an flexible.
You could write a custom attribute that can test a condition and either allow an empty field or not allow it.
The below is a simple demo i put together for the guys here. You'll need to modify to suit your purposes/
using System.ComponentModel.DataAnnotations;
namespace CustomAttributes
{
[System.AttributeUsage(System.AttributeTargets.Property)]
public class MinimumLength : ValidationAttribute
{
public int Length { get; set; }
public MinimumLength()
{
}
public override bool IsValid(object obj)
{
string value = (string)obj;
if (string.IsNullOrEmpty(value)) return false;
if (value.Length < this.Length)
return false;
else
return true;
}
}
}
Model;
using CustomAttributes;
namespace Models
{
public class Application
{
[MinimumLength(Length=20)]
public string name { get; set; }
}
}
Controller
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(Application b)
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
if (ModelState.IsValid)
{
return RedirectToAction("MyOtherAction");
}
return View(b);
}
enter code here

Resources