I'm trying to figure out if the MODEL is even used in this scenario or whether CurrentUmbracoPage just deals with data in the ModelState, ViewData etc.
What would be the pattern to use in this case: search > post > display results
Yes, it can feel a little bit weird, because Umbraco itself uses a default MVC Controller (RenderMvcController) implementation to render all incoming requests to Umbraco for content.
The SurfaceController is designed to umm sit on the 'Surface' of this interaction. It does not interact directly with the ViewModel of the content page when it is rendered, which is why your setting of the property isn't working.
It can interact with 'ModelState' as it needs to check if the form data being posted is valid, so you can manipuate the ModelState if needs be to return error messages, and returning CurrentUmbracoPage, effectively runs the RenderMvcController again, but with the ModelState for your form intact - to show the error messages.
You can therefore add custom messages from a SurfaceController handling a form postback by using TempData or the ViewBag (https://rachelappel.com/2014/01/02/when-to-use-viewbag-viewdata-or-tempdata-in-asp-net-mvc-3-applications/)
TempData["successMessage"] = "Yey it worked";
So think of the SurfaceController really as only handling a postback, and determining whether the posted values are valid or not, if they are not valid it returns the CurrentUmbracoPage and displays error messages, but if all is ok - then depending what the form is intended to do, you might send an email, log entries to a db table, etc, and then redirect to another page, or back to the current page clearing modelstate by return RedirectToCurrentUmbracoPage (there is a full list of options here: https://our.umbraco.com/documentation/reference/routing/surface-controllers-actions)
So how does that help you display search results?
(It doesnt'!)
The pattern would be once your SurfaceController has handled the form post and made sure it's a valid request - would be to 'redirect' with the search parameters on a querystring to a GET route that actually performs the search and can render the view containing the results.
The common way to do this with Umbraco is to create a hijacked RenderMvcController:
If you create a SearchResults Document Type in Umbraco then any request to a page based on that DocumentType will be routed via your Custom MVC Controller IF it matches the alias of the DocumentType and inherits from RenderMvcController class:
public class SearchResultsController : Umbraco.Web.Mvc.RenderMvcController
{
public ActionResult Index(ContentModel model, string searchTerm="")
{
// you are in control here!
// if you create your own ViewModel that inherits from ContentModel,
you can set it's custom properties here:
var viewModel = new SearchResultsViewModel(model);
//do the search!
viewModel.SearchTerm = searchTerm;
viewModel.SearchResults = _mySuperSearchService(searchTerm);
// return the 'model' to the selected template/view for this page.
return CurrentTemplate(viewModel);
}
}
You'll need to update your template view to inherit from your custom view model
@inherits UmbracoViewPage<SearchResultsViewModel>
But then you'll be able to use the properties on your model in your view
eg
@if (Model.HasSearchResults){
<h2>Search Results</h2>
@foreach (var result in Model.SearchResults){
<li>@result.Name</li>
}
}
So yeah, it's a little bit convoluted, but if you think SurfaceController just handles the form post, and custom RenderMvcController is responsible for displaying things, then it sort of isn't so bad as a pattern once you've got it working once.
Does CurrentUmbracoPage keep the view model?
I am trying to implement a simple search page but when I return from the HttpPost action the Model is null.
The search form is implemented as partial views and called from the template page by Html.Action.
When I post to the controller and return CurrentUmbracoPage:
The view renders the message:
Alas, the message is always NULL.
I'm trying to figure out if the MODEL is even used in this scenario or whether CurrentUmbracoPage just deals with data in the ModelState, ViewData etc.
What would be the pattern to use in this case: search > post > display results
Help greatly appreciated.
Hi Anthony
Yes, it can feel a little bit weird, because Umbraco itself uses a default MVC Controller (RenderMvcController) implementation to render all incoming requests to Umbraco for content.
The SurfaceController is designed to umm sit on the 'Surface' of this interaction. It does not interact directly with the ViewModel of the content page when it is rendered, which is why your setting of the property isn't working.
It can interact with 'ModelState' as it needs to check if the form data being posted is valid, so you can manipuate the ModelState if needs be to return error messages, and returning CurrentUmbracoPage, effectively runs the RenderMvcController again, but with the ModelState for your form intact - to show the error messages.
You can therefore add custom messages from a SurfaceController handling a form postback by using TempData or the ViewBag (https://rachelappel.com/2014/01/02/when-to-use-viewbag-viewdata-or-tempdata-in-asp-net-mvc-3-applications/)
So think of the SurfaceController really as only handling a postback, and determining whether the posted values are valid or not, if they are not valid it returns the CurrentUmbracoPage and displays error messages, but if all is ok - then depending what the form is intended to do, you might send an email, log entries to a db table, etc, and then redirect to another page, or back to the current page clearing modelstate by return RedirectToCurrentUmbracoPage (there is a full list of options here: https://our.umbraco.com/documentation/reference/routing/surface-controllers-actions)
So how does that help you display search results?
(It doesnt'!)
The pattern would be once your SurfaceController has handled the form post and made sure it's a valid request - would be to 'redirect' with the search parameters on a querystring to a GET route that actually performs the search and can render the view containing the results.
The common way to do this with Umbraco is to create a hijacked RenderMvcController:
https://our.umbraco.com/Documentation/Reference/Routing/custom-controllers
If you create a SearchResults Document Type in Umbraco then any request to a page based on that DocumentType will be routed via your Custom MVC Controller IF it matches the alias of the DocumentType and inherits from RenderMvcController class:
You'll need to update your template view to inherit from your custom view model
But then you'll be able to use the properties on your model in your view
eg
}
So yeah, it's a little bit convoluted, but if you think SurfaceController just handles the form post, and custom RenderMvcController is responsible for displaying things, then it sort of isn't so bad as a pattern once you've got it working once.
regards
marc
I just want to thank you for taking the time out to explain this! Thanks!
is working on a reply...