Return to second to last URL in MVC (return View w

2019-07-07 17:34发布

问题:

I'm working on an MVC5 application. On the home screen is a grid allowing users to view Data and be transferred to a number of Views for various actions on each record. One of these is an [EDIT].

The issue I'm encountering is as follows: due to the amount of data it is convenient to Filter the data down (say to a specific location) and then Edit records from there. The filter on this grid (Grid.MVC from CodePlex) performs filtering partially by modifying the URL (http://homeURL/?grid-filter=Location.DEPT__1__accounting) such as 1 being Equals, 2 being Cotains, 3 being StartsWith, and 4 being EndsWith and then after the next 2 underscores being the search criteria.

This functions fine, however upon [POST] return from the Edit the user currently is returned to main Index view without the filtering criteria still set (forcing them to go in over and over and add filtering criteria before performing the similar EDIT on records of the same criteria).

My POST-EDIT method is currently setup to include:

        if (ModelState.IsValid)
        {
            collection.MODIFIED_DATE = DateTime.Now;
            collection.MODIFIED_BY = System.Environment.UserName;

            db.Entry(collection).State = EntityState.Modified;
            await db.SaveChangesAsync();
            return RedirectToAction("Index", "Home");
        }

For my attempts I had first thought to return the View with the updated collection (return View(collection)) but this of course just takes me back to the EDIT view, not the home view with the data grid filtered down as previously specified. I considered adding a field in the database, something like LAST_FILTERED_URL, but this just feels like an overgrown band-aid.

Does anyone know of a clean way to go about this?


EDIT:

I had thought to do something similar to Andrea's suggestion early on, but had not thought of doing an explicit redirect with the Parameter of the url-filter passed in the Redirect. Below is my current code for the GET/POST Edit:

    // GET: ENITTY_Collection/Edit/5
    public async Task<ActionResult> Edit(int id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        ENTITY_COLLECTION entity_Collection = await db.ENTITY_COLLECTION.FindAsync(id);
        if (entity_Collection == null)
        {
            return HttpNotFound();
        }

        // Other code for Controls on the View

        return View(entity_Collection);
    }

        // POST: ENTITY_Collection/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Edit([Bind(Include = "Id,One_Id,Two_Id,Three_Id,Four_Id,Five_Id,Six_Id,field7,field8,field9,...field18,created_date,created_by,modified_date,modified_by")] ENTITY_COLLECTION entity_Collection)
        {
            if (ModelState.IsValid)
            {
                entity_Collection.MODIFIED_DATE = DateTime.Now;
                entity_Collection.MODIFIED_BY = System.Environment.UserName;

                db.Entry(entity_Collection).State = EntityState.Modified;
                await db.SaveChangesAsync();
                //return RedirectToAction("Index", "Home");
                return View(entity_Collection);
            }

            // Other code for if Model is Invalid before returning to View.

            return View(entity_Collection);
        }

I like Andrea's suggestion, but I still need a good way to store the URL the user has when they first navigate to the GET-Edit View, and then use that filtered URL value to return the user to that previous location & filter option when the POST-Edit completes and changes have saved.

Any thoughts?

回答1:

Have you tried changing passing the current filter to redirect to action as follows? Note: I am assuming that:

  1. you are redirecting to the same controller
  2. you have a controller parameter called currentFilterValue

    RedirectToAction("Index", "Home",new { grid-filter = currentFilterValue });



回答2:

The default LoginController for an MVC project from Microsoft includes a bunch of methods that use a returnUrl parameter. Using this practice, you could include a return URL when opening the editor, that when editing is done, returns the user back to the prior screen with the filters intact (assuming they are in the URL).

My base class for view models has a property for storing the ReturnURL, which is then stored as a hidden if set.

@Html.HiddenFor(model => model.ReturnUrl)

My action that posts from edit then has this logic:

if (viewModel.ReturnUrl.IsNotNullOrEmptyTrimmed())
{
    return RedirectToLocal(viewModel.ReturnUrl, "ActionName", "ControllerName");
}
else
{
    // Default hard coded redirect
}

In order to prevent some injections, you will want a validation method (called above) like this for ensuring the URL is valid:

protected ActionResult RedirectToLocal(string returnUrl, string defaultAction, string defaultController)
{
    try
    {
        if (returnUrl.IsNullOrEmptyTrimmed())
            return RedirectToAction(defaultAction, defaultController);

        if (Url.IsLocalUrl(returnUrl))
            return Redirect(returnUrl);

        Uri returnUri = new Uri(returnUrl);
        if (Url.IsLocalUrl(returnUri.AbsolutePath))
        {
            return Redirect(returnUrl);
        }
    }
    catch
    {
    }

    return RedirectToAction(defaultAction, defaultController);
}

Hopefully this gets you some ideas and on the right track.



回答3:

I'm not sure if this is the most correct way of going about what I'm after, but what appears to be working for me is the use of a Session value.

In my GET method I store the URL:

Session["returnURL"] = Request.UrlReferrer.AbsoluteUri;

Then in my POST I use this value in a Redirect() after saving changes to the record:

var returnURL = (Session["returnURL"] != null) ? Session["returnURL"].ToString() : Url.Action("Index", "Home");
return Redirect(returnURL);

So far all initial testing is resulting in a return to the main view with all sorting/filtering criteria in place before the record was entered into for update.