简体   繁体   中英

Edit in mvc4 didn't work

I want to edit this data in database and return new data
when i click on save button data doesn't change Here is controller :

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(CustomPerformancePerformersModel customPerformancePerformersModel)
    {
        if (ModelState.IsValid)
        {
            int perfromanceId = Convert.ToInt32(TempData.Peek("CurrentPerformanceId"));
            customPerformancePerformersModel.performanceObj = db.Performances.Where(x => x.PerformanceId == perfromanceId).FirstOrDefault();
            db.Entry(customPerformancePerformersModel.performanceObj).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.EventId = new SelectList(db.Events, "EventId", "Name", customPerformancePerformersModel.performanceObj.EventId);
        ViewBag.VenueId = new SelectList(db.Venues, "VenueId", "Name", customPerformancePerformersModel.performanceObj.VenueId);
        ViewBag.Performers = new SelectList(db.PerformerPerformances, "Performers", "Name", customPerformancePerformersModel.performanceObj.PerformerPerformances);
        return View(customPerformancePerformersModel.performanceObj);
    }

and here is the html:

   <div class="form-group">
        @Html.LabelFor(model => model.performanceObj.IsVisible, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <div class="checkbox">
                @Html.EditorFor(model => model.performanceObj.IsVisible)
                @Html.ValidationMessageFor(model => model.performanceObj.IsVisible, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.performanceObj.IsFeatured, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <div class="checkbox">
                @Html.EditorFor(model => model.performanceObj.IsFeatured)
                @Html.ValidationMessageFor(model => model.performanceObj.IsFeatured, "", new { @class = "text-danger" })
            </div>
        </div>

Try the following:

    if (ModelState.IsValid)
    {
        int perfromanceId = Convert.ToInt32(TempData.Peek("CurrentPerformanceId"));

        // There is no need to use Where. FirstOrDefault has an overload using predicates.
        var savedPerformance = db.Performances.FirstOrDefault(x => x.PerformanceId == perfromanceId); 

        // If the performance couldn't be found, then you could add the error to the model state and return it to the view.
        if(savedPerformance == null)
            return View(customPerformancePerformersModel.performanceObj);

        // Update properties from performance in database with new performance.
        savedPerformance.someProperty = customPerformancePerformersModel.performanceObj.someProperty;

        db.Performances.Attach(savedPerformance);
        db.Entry(savedPerformance ).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }

Ideally your code will look something like the following:

public ActionResult Edit(int performanceId)
{
    var model = db.Performances.FirstOrDefault(m => m.PerformanceId == performanceId);
    return View(model);
}

[HttpPost] //[HttpPatch] is technically correct, but most people I see tend to use only GET and POST actions.
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomPerformancePerformersModel model)
{
    if (ModelState.IsValid)
    {
        db.Entry(model).State = EntityState.Modified;
        db.SaveChanges();
    }
}

You're retrieving the object from the database and tracking it in your GET action, modifying it using your form, then marking it as modified in your update action. This is strictly if you're using the MVC pattern, and will look different (see below) if you're using separate data and view models. You'll likely run into trouble with this approach if your view doesn't have fields (hidden or not) for all properties on your model.

Using separate data and view models, you'd have something like this:

public ActionResult Edit(int performanceId)
{
    var performance = db.Performances.FirstOrDefault(m => m.PerformanceId == performanceId);
    var model = new PerformanceViewModel(performance); //In this constructor, copy properties from your data model to your view model
    return View(model);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(PerformanceViewModel model)
{
    var performance = db.Performances.FirstOrDefault(m => m.PerformanceId == model.PerformanceId);
    model.Update(performance);
    db.SaveChanges();

}

With a sample view model:

public class PerformanceViewModel
{

    public PerformanceViewModel(CustomPerformanceePerformersModel model)
    {
        PerformanceId = model.performanceObj.PerformanceId;
        IsVisible = model.performanceObj.IsVisible;
        IsFeatured = model.performanceObj.IsFeatured;
    }
    public int PerformanceId { get; set; }

    public bool IsVisible { get; set; }

    public bool IsFeatured { get; set; }


    public void Update(CustomPerformancePerformersModel model)
    {
        model.performanceObj.IsVisible = IsVisible;
        model.performanceObj.IsFeatured = IsFeatured;
    }
}

Here you're creating a separate object (view model) that holds only the necessary data for your view, then using the data from that object to update your data model. I prefer this because it takes the ability to effectively directly modify the database, and because you can do any necessary intermediate processing (casting strings to bools, et cetera) in the Update(Model) method.

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