Electric Sheep
Electric Sheep

Reputation: 4330

How do I pass data from a controller action to child action in the layout template?

I have a search form that is displayed on every page in my application. It is generated using a child action:

[ChildActionOnly]
public PartialViewResult Form(SearchFormViewModel model)
{
    model.LanguageList = ReferenceService.GetLanguageList();
    model.SubjectList = ReferenceService.GetSubjectList();

    return PartialView("_SearchForm", model);
}

and the following view model

public class SearchFormViewModel
{
    public int Page { get; set; }

    public string Name { get; set; }

    public string Location { get; set; }

    public IList<Subject> SubjectList { get; internal set; }

    public IList<Language> LanguageList { get; internal set; }
}

and called from my layout, which all my views inherit from.

@Html.Action("Form", "Search")

The form is submitted with a GET e.g. /search/results?Subject=1&Location=United+Kingdom, so the form is populated on the results page, and the action for page performs the search and displays the results.

public ViewResult Results(SearchFormViewModel searchModel)
{
...

I also have an action to handle some friendly urls for searching e.g. /computing/united-kingdom which uses a custom route to direct to correct action.

public ViewResult FriendlyResults(string subject, string location)

This action matches the url components to search parameters, performs a search and displays the results.

What I want to do is populate the search form for friendly urls i.e. pass the search parameters to the Form child action, so that you can see what you have searched for.

The only way I can think to do this is do store the 'friendly search' model in the ViewBag, and pass this as a parameter to the Form action, if it is populated. This doesn't feel right to me.

Is there a better way or approach to do this?

Upvotes: 2

Views: 1073

Answers (1)

Pierluc SS
Pierluc SS

Reputation: 3176

If you want to refer to it in the layout, you have to use ViewBag. But if you can refer to it directly in the view (could be in a section as well) you could simply have a model that would encapsulates the search query and the results. A shorten down example would like the following:

public class SearchResponse {
    public List<SearchResults> Results { get; set; }
    public SearchQuery { get; set; }
}

public class SearchQuery{
   public string Subject { get; set; }
   public string Location { get; set; }
}

So then, you would have stricly typed view of type SearchResponse

EDIT

In your case, I would simply call @Html.Action("Form", "Search", ViewBag.SearchQuery) and only set the ViewBag.SearchQuery into the Results(SearchFormViewModel searchModel) action, therefore passing in null when there ViewBag's property is not set.

Upvotes: 2

Related Questions