Search code examples
asp.net-mvcmodelcontrollerstempdata

MVC 3 Action on different controller, but need ViewModel


I'm searching for the best possible way to solve the following problem: I have a search page, with different criterias that can be selected, which are availible in the SearchViewModel. Now the search returns a list of SearchResults, which are products. Those can be added directly to the basket. Now the problem is, the action for adding the item to the basket is on the BasketController and not the SearchController. When the user clicks it, he is returned to the SearchPage but loses all the selections he has made.

if (Request.UrlReferrer != null)
        return Redirect(Request.UrlReferrer.ToString());

I have tried working around the problem using TempData, but I get a "The result of a query cannot be enumerated more than once."-Exception.

private SearchViewModel EnsureViewModel(SearchViewModel viewModel)
    {
        if (TempData["SearchModel"] != null && viewModel.SearchResult == null)
            viewModel = TempData["SearchModel"] as SearchViewModel;

        TempData["SearchModel"] = viewModel;
        return viewModel;
    }

Here where I display the list of my results in the model, the exception is thrown:

@Html.DisplayFor(p => Model.SearchResult)

I've also considered that there might be a way to do this using a partial view? Of course, my last ressource is just duplicating the code, but I'm not thrilled by that idea...

Any ideas are appreciated, thanks =)


Edit The call for the controller is made using the form as following:

@using (Html.BeginForm("Add", "Basket", new { id = Model.Name } ))
    {
        @Html.TextBox("amount", "1", new { name="amount", maxlength=7, @class = "txtfield number" })
        <button><img src="@Url.Content("~/Content/images/icon_basket.gif")" border="0" width="14" height="10" class="basket" /></button>
    }       

Solution

  • I think the Redirect is what's blowing up the TempData, try replacing "Redirect" in your controller code with "View" and pass it the view name (not the whole url).

    (Note: if your controller action was doing anything to populate a view model you'll need to copy that code and insert it just before your call to the View (I pull it out into a private method and call it from both places))