asp.net-mvcbuttonreturnsave

Button to save edit in its current model and then return you to previous Details view of a different model


I am using ASP.NET MVC. I have a PIF controller and on the details view, I have data showing from a variety of other models, one of which is called SAEs (I will use this as the example). For each of these models, I have buttons to either create a new entry or to edit an existing entry. These buttons take you out of the PIF model, to the SAEs model.

So far, so good. On the SAEs Create/Edit views, in addition to the normal Save button, I would like an additional button to save their entry into the SAEs Model and to then take them back to the PIF Details page from where they came (Project ID = Project ID).

How do you get an additional save button on the same page? I've managed to create an additional button "Save and go back to previous page" and while it takes you back to that page, it doesn't save before doing so. I've Googled and am very lost by it all. I suspect I have to do something in the HttpPost part of the SAE Create and Edit parts of the controller but simply have no clue. Help is much appreciated.

Here is the Edit part of the SAEs controller.

// GET: SAEs/Edit/5
public async Task<IActionResult> Edit(int? id)
{
     if (id == null || _context.SAE == null)
     {
         return NotFound();
     }

     var sAE = await _context.SAE.FindAsync(id);

     if (sAE == null)
     {
         return NotFound();
     }

     ViewData["ProjectID"] = new SelectList(_context.PIF, "ProjectID", "ProjectID", sAE.ProjectID);

     var saesusars = _context.SAESUSAR.ToList();
     ViewBag.saesusarslist = saesusars;

     var subcats = _context.SAESubCat.ToList();
     ViewBag.subcatslist = subcats;

     var report = _context.YesNoList.ToList();
     ViewBag.reportlist = report;
    
     return View(sAE);
}

// POST: SAEs/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("SAEID,ProjectID,SAEorSUSAR,DateofEvent,DateofNotification,SAECategory,PatientStudyNumber,ReportedToRDOG,DateReportedtoRDOG")] SAE sAE)
{
     if (id != sAE.SAEID)
     {
         return NotFound();
     }

     SAEValidator saevalidator = new SAEValidator();
     ValidationResult result = saevalidator.Validate(sAE);

     if (ModelState.IsValid)
     {
         try
         {
             _context.Update(sAE);
             await _context.SaveChangesAsync();
         }
         catch (DbUpdateConcurrencyException)
         {
             if (!SAEExists(sAE.SAEID))
             {
                 return NotFound();
             }
             else
             {
                 throw;
             }
         }
     }

     //return RedirectToAction(nameof(Index));

     else 
     {
         foreach (var failure in result.Errors)
         {
             ModelState.AddModelError(failure.PropertyName, failure.ErrorMessage);
         }
     }
     
     ViewData["ProjectID"] = new SelectList(_context.PIF, "ProjectID", "ProjectID", sAE.ProjectID);
     var saesusars = _context.SAESUSAR.ToList();
     ViewBag.saesusarslist = saesusars;

     var subcats = _context.SAESubCat.ToList();
     ViewBag.subcatslist = subcats;

     var report = _context.YesNoList.ToList();
     ViewBag.reportlist = report;

     //return View(sAE);
     return RedirectToAction(nameof(Index));
}

And here is a snippet of the Edit.cshtml:

        <div class="form-group">
            <input type="submit" value="Save" class="btn btn-primary" />
        </div>
    </form>
</div>

<div>
    <a asp-action="Index">Back to List</a>
         
    <a input type="submit" class="btn btn-primary" href="javascript:history.back()">Save and go back to previous page</a>
   
</div>

Solution

  • From my thought as you are fully working with MVC (model-binding with model state validation), you can provide the action and returnUrl (with previous page URL) to your Edit action.

    <form>
      <input type="hidden" id="returnUrl" name="returnUrl" value="" />
      <div class="form-group">
          <input type="submit" name="action" value="Save" class="btn btn-primary" />
    
          <br />
    
          <button type="submit" name="action" value="SaveAndBack" class="btn btn-primary">Save and go back to previous page</button>
      </div>
    </form>
    
    <script>
        document.getElementById("returnUrl").value = document.referrer;
    </script>
    

    And in your Edit action, it should based on the action and the returnUrl to perform redirection.

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(int id, 
        [Bind("SAEID,ProjectID,SAEorSUSAR,DateofEvent,DateofNotification,SAECategory,PatientStudyNumber,ReportedToRDOG,DateReportedtoRDOG")] SAE sAE, 
        string action, 
        string returnUrl)
    {
        ...
    
        // Redirection after model validation passed and successfully update to database
    
        if (action == "SaveAndBack" && !String.IsNullOrEmpty(returnUrl))
        {
            return Redirect(returnUrl);
        }
    
        return RedirectToAction(nameof(Index));
    }