Search code examples
c#asp.net-mvc-5

ASP.NET MVC: How can I redirect to a previous action or a specific action after form submission?


My pages have the form:

  • site.com/inventory/Query
  • site.com/inventory/Results
  • site.com/inventory/Details?item=123

View

On Details, I have a button to upload the item data sheet in the View:

using (Html.BeginForm("Upload", "Inventory", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.TextBox("file", "", new { type = "file", id = "file", accept = "Application/PDF" })
    @Html.HiddenFor(m => m.ItemNumber, "item")
    <button type="submit" class="btn btn-primary">Upload</button>
}

The initial Query is a lot of work on the database (it takes about 20 seconds). Instead of returning to it, I would like to get back to the Results page after uploading the support document for this item on the Detail page.

I found a similar question:

How do I redirect to the previous action in ASP.NET MVC?

I modified my code to include this Redirect:

Controller

[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult Upload(HttpPostedFileBase file, string item)
{
    // saves the file (code hidden)
    return Redirect($"{Request.UrlReferrer}");
}

However, the Redirect above successfully returns me to the Details page.

Is there a way to redirect all the way back to the Results page?

Update

I have tried updating to this, based on the answer below:

[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult Upload(HttpPostedFileBase file, string item)
{
    // saves the file (code hidden)
    var model = Session["InventoryModelObject"] as InventoryModel;
    return RedirectToAction("Results", model);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Results(InventoryModel model)
{
    var list = new List<Source>();
    list.AddRange(model.GateWaySelectedSources.Where(x => x.Item2));
    list.AddRange(model.BowSelectedSources.Where(x => x.Item2));
    list.AddRange(model.CuddySelectedSources.Where(x => x.Item2));
    list.AddRange(model.WSSSelectedSources.Where(x => x.Item2));
    list.AddRange(model.DeckSelectedSources.Where(x => x.Item2));
    list.AddRange(model.ASelectedSources.Where(x => x.Item2));
    list.AddRange(model.RSelectedSources.Where(x => x.Item2));
    list.AddRange(model.PSelectedSources.Where(x => x.Item2));
    var dlnSql = "";
    foreach (var item in list)
    {
        if (string.IsNullOrEmpty(dlnSql))
        {
            dlnSql = " AND DAMDLN IN (";
        }
        dlnSql += $"'{item.Item1}', ";
    }
    if (!string.IsNullOrEmpty(dlnSql))
    {
        dlnSql += "' ')";
    }
    var statusSource = model.StatusSelectedSources.Where(x => x.Item2);
    var statSql = "";
    if (statusSource.Any(x => x.Item1 == "RT"))
    {
        statSql = " AND DASTAT IN ('RT', ";
    }
    if (statusSource.Any(x => x.Item1 == "SN"))
    {
        statSql = string.IsNullOrEmpty(statSql) ? " AND DASTAT IN ('SN', " : statSql + "'SN', ";
    }
    if (statusSource.Any(x => x.Item1 == "DL"))
    {
        statSql = string.IsNullOrEmpty(statSql) ? " AND DASTAT IN ('DL', " : statSql + "'DL', ";
    }
    if (!string.IsNullOrEmpty(statSql))
    {
        statSql += "' ') ";
    }
    var yearSql = "";
    if (!model.AllYears && model.YearSelectedSources.Any(x => x.Item2))
    {
        foreach (var item in model.YearSelectedSources)
        {
            if (item.Item2)
            {
                yearSql += $"'{item.Item1}', ";
            }
        }
        if (!string.IsNullOrEmpty(yearSql))
        {
            yearSql = $" AND DAPRGY IN ({yearSql} '0') ";
        }
    }
    var sql = $@"
SELECT DASTAT, DADTRS, TRIM(DASRNO) AS DASRNO, DAMDLN, DAORNO, DAENGD, DAEXTC, DACONF, DACUST, DADTIN
FROM {ViewBag.Library}.DLRINVAPF
WHERE DADLRN={Session["DealershipID"]}{yearSql}{statSql}{dlnSql}";
    Session["InventoryModelObject"] = model;
    return View(result);
}

But this is trying to send my model as a JSON string parameter instead of calling the method that accepts the model.

screenshot


Solution

  • There isn't any "double back" in ASP.NET MVC. But you could redirect to the desired view using one of two approaches

    1. In case you have a permanent flow you could just redirect to desired action providing the required parameter to restore view
    return RedirectToAction("Results", ...);
    
    1. Add returnUrl query or post form parameter to redirect to after form submitted. For example:
    using (Html.BeginForm("Upload", "Inventory", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.AntiForgeryToken()
        @Html.TextBox("file", "", new { type = "file", id = "file", accept = "Application/PDF" })
        <input type="hidden" name="returnUrl" value="@Request.UrlReferrer" />
        @Html.HiddenFor(m => m.ItemNumber, "item")
        <button type="submit" class="btn btn-primary">Upload</button>
    }
    

    Or you could put that into the URL query string.