简体   繁体   中英

Implementing MVC design pattern with Repositories and Mapping, C#

I have a problem with implementing the CRUD operations by using repositories, view models, and mapping in my ASP.Net MVC project. The "details"(read the information about one object) and "index"(read the whole list of objects), controllers are working.

I am mapping the Model to ViewModel and then display it in View . But for Create , Update and Delete operations, I should map the ViewModel to the Model . Could you tell me where am I wrong?

Model

 public class User
 {
     [Key]
     public int Id { get; set; }

     [Required]
     public string Name { get; set; }

     [Unique]
     [Required]
     [MaxLength(100)]
     public string Email { get; set; }

     [Required]
     public string Password { get; set; }

     public string Phone { get; set; }

     public bool IsAdmin { get; set; }
}

Base repository

public class BaseRepository<T> : IBaseRepository<T> where T : class
{
    private RushHourContext db = null;
    private DbSet<T> table = null;

    public BaseRepository()
    {
        this.db = new RushHourContext();
        table = db.Set<T>();
    }

    public BaseRepository(RushHourContext db)
    {
        this.db = db;
        table = db.Set<T>();
    }

    public IEnumerable<T> SelectAll()
    {
        return table.ToList();
    }

    public T SelectByID(object id)
    {
        return table.Find(id);
    }

    public void Insert(T obj)
    {
        table.Add(obj);
    }

    public void Update(T obj)
    {
        table.Attach(obj);
        db.Entry(obj).State = EntityState.Modified;
    }

    public void Delete(object id)
    {
        T existing = table.Find(id);
        table.Remove(existing);
    }

    public void Save()
    {
        db.SaveChanges();
    }
}

Interface for Repository

public interface IBaseRepository<T> where T : class
{
    IEnumerable<T> SelectAll();
    T SelectByID(object id);
    void Insert(T obj);
    void Update(T obj);
    void Delete(object id);
    void Save();
}

Controller

   private RushHourContext _db = new RushHourContext();
   private IBaseRepository<User> _repository = null;

   public UsersController()
   {
       this._repository = new BaseRepository<User>();
   }

   public ActionResult Index()
   {
       if (!LoginUserSession.IsStateAdmin)
       {
           return RedirectToAction("Login");
       }
       var users = _repository.SelectAll().ToList();
       var userViewModel = Mapper.Map<List<UserViewModel>>(users);
       return View(userViewModel);
   }

   public ActionResult Details(int? id)
   {
       var users = _repository.SelectByID(id);

       var userViewModel = Mapper.Map<UserViewModel>(users);
       return View(userViewModel);
   }

   public ActionResult Create(User user)
   {
       var users = _repository.Insert(user); // THIS CODE HERE IS WRONG

       var userViewModel = Mapper.Map<User>(users);

       return View(userViewModel);
   }

UserViewModel

public class UserViewModel
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Please enter User Name.")]
    [Display(Name = "User Name")]
    public string Name { get; set; }

    [MaxLength(100)]
    [Display(Name = "Email Address")]
    public string Email { get; set; }

    [Required]
    [Display(Name = "Password")]
    public string Password { get; set; }

    public string Phone { get; set; }

    public bool IsAdmin { get; set; }
}

View

   @model RushHour.ViewModels.UserViewModel

@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>


<div>
    @Html.AntiForgeryToken()


    @using (Html.BeginForm("Create", "Users", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.AntiForgeryToken()

       <div>@Html.LabelFor(model => model.Id)</div> 
       <div>@Html.TextBoxFor(model => model.Id)</div> 
       <div>@Html.ValidationMessageFor(model => model.Id)</div>

        <div>@Html.LabelFor(model => model.Name)</div>
        <div>@Html.TextBoxFor(model => model.Name)</div>
        <div>@Html.ValidationMessageFor(model => model.Name)</div>

        <div>@Html.LabelFor(model => model.Password)</div>
        <div>@Html.TextBoxFor(model => model.Password)</div>
        <div>@Html.ValidationMessageFor(model => model.Password)</div>

        <div>@Html.LabelFor(model => model.Email)</div>
        <div>@Html.TextBoxFor(model => model.Email)</div>
        <div>@Html.ValidationMessageFor(model => model.Email)</div>

        <div>@Html.LabelFor(model => model.Phone)</div>
        <div>@Html.TextBoxFor(model => model.Phone)</div>
        <div>@Html.ValidationMessageFor(model => model.Phone)</div>


        <div>@Html.LabelFor(model => model.IsAdmin)</div>
        <div>@Html.TextBoxFor(model => model.IsAdmin)</div>
        <div>@Html.ValidationMessageFor(model => model.IsAdmin)</div>


        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    }
</div>
  1. Your model in your Create view is your UserViewModel and that should be passed into the controller, not User .

  2. The pattern you have set up suggests the user will first be on the Create view while entering new user information. So, they will navigate to this view without passing any objects to it on their first trip. If that's the case, you'll want a parameterless constructor for the first visit where you'll just create a new UserViewModel and pass it in. You're then navigating back to this view after user creation which will present a form to them and be very confusing for user experience. You'll probably want to redirect to a confirmation page or the login page with a message saying user created.

  3. Whenever you make changes to the data, EntityFramework won't make those changes until you call SaveChanges on the repository. It's odd that you aren't saving your new user immediately after it being created.

DbSet.Add

DbContext.SaveChanges

For the create function use UserViewModel instead of User . Then map from UserViewModel to User to insert in database. After, if you want to display the saved data, then return UserViewModel object.

Try the following code.

[HttpPost]
public ActionResult Create(UserViewModel userViewModel)
{ 
   var user = new User();
   var newUser = Mapper.Map(userViewModel, user); 
  _repository.Insert(newUser);
  _repository.Save();
  return View(userViewModel);
}

you can do like this:

    [HttpPost]
    public ActionResult Create(UserViewModel userViewModel)
    {
        var user = Mapper.Map<User>(userViewModel);
        _reoisitory.Add(user);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM