I am trying to move code from view to controller, learning how to make use of MVC in Umbraco. My goal is to create a partial view for the search box and submit button and a search results page that displays search results. Sounds simple, but to the life of me i cant get it to work via SufaceController or RenderMvcController. I keep getting errors in my code.
I have the partial search term form, this i would like to render on header and search results page.
This works fine : )
This is my Controller, named after my DocType in backoffice
using System;
using System.Web.Mvc;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
namespace ScottishPrenier.Core.Controllers
{
public class FindController : SurfaceController
{
public ActionResult Finder(ContentModel model, string query)
{
var searchTerm = string.Empty;
searchTerm = string.IsNullOrWhiteSpace(query) ? String.Empty : query;
if (searchTerm == String.Empty)
{
ViewBag.q = "Enter search Term";
return CurrentUmbracoPage();
}
ViewBag.q = searchTerm;
return CurrentUmbracoPage();
}
public ActionResult Form(ContentModel model)
{
return PartialView("Finder Partial View", model);
}
}
}
This is my search results page, find.cshtml
@inherits Umbraco.Web.Mvc.UmbracoViewPage
@{
Layout = "master.cshtml";
}
@* the fun starts here *@
@{ Html.RenderAction("Form", "Find", new { model = Model, query = Request.QueryString["query"] }); }
The above code is a starting block for me to get the search results page rendering via direct access or via the search term form. The above code works as expected, search results page renders ok.
My next step is to make use of a custom model to hold title link and excerpt of search results from the search term and render them on the search results page.
My custom model is
using System.Collections.Generic;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web.Models;
namespace ScottishPrenier.Core.Models
{
public class SearchResult : ContentModel
{
public SearchResult(IPublishedContent content) : base(content)
{
}
public string Title { get; set; }
public string Excerpt { get; set; }
public string Link { get; set; }
public IEnumerable<IPublishedContent> SearchResults { get; set; }
}
}
Here is where i get stuck, i make a change to my search results page Find.cshtml to inherit my custom model.
Cannot bind source type Umbraco.Web.Models.ContentModel to model type SearchResult.
passing the custom model to the controller makes no difference. Changing my controller to use RenderMvcController causes The name 'CurrentUmbracoPage' does not exist in the current context.
Im not sure how i can make my custom model fit in my current code to display search results on my search results page
Anybody able to assist or advise where im going wrong ?
Generally the rule of thumb for Umbraco is to use a SurfaceController that has the job of handling a 'post back' from a form - and also for convenient ChildActions for rendering a PartialView inside your Umbraco template, eg to present the form.
However, you would typically use a RenderMvcController to handle the rendering of content for a request.
Therefore in this kind of pattern you often end up with two Controllers, one a SurfaceController that has a child action that Renders the form, and an Action that handles the postback from the form - checks validation etc
but if the form posting back validates then the SurfaceController would usually redirect to a GetRequest to a RenderMvcController that has the job of performing the search, and passing a custom model to the view to display the results.
So if your Search Results Page has Document Type 'SearchPage'
Create a controller called 'SearchPageController' that inherits from RenderMvcController
public class SearchPageController : RenderMvcController
{
public ActionResult Index(ContentModel model, string searchTerm = "", int page = 1)
{
//create your custom view model
SearchPageViewModel searchPageViewModel = new SearchPageViewModel(model.Content, model.CurrentCulture));
//do the search
searchPageViewModel.SearchResults = SiteSearchService.SearchSite(searchTerm, page);
then return the custom model:
return CurrentTemplate(searchPageViewModel);
}
}
Then your view can inherit this custom model
@inherits UmbracoViewPage<SearchPageViewModel>
You can render your search form either directly from a partial:
<div>
@Html.Partial("SearchForm", new SiteSearchCriteria() { SearchTerm = Model.SearchResults.SearchTerm })
</div>
or via a child action @Html.Action("RenderSearchForm","SearchFormSurface")
and have a property on your custom model determining if there are search results
And then your SurfaceController could look something like this:
public class SearchController : SurfaceController
{
[HttpPost]
public ActionResult Search(SiteSearchCriteria searchCriteria)
{
if (!ModelState.IsValid)
{
return CurrentUmbracoPage();
}
else
{
var searchResultsPage = SiteService.GetSearchPage();
return RedirectToUmbracoPage(searchResultsPage,"searchTerm=" + searchCriteria.SearchTerm);
}
}
}
so basically all it does is validate the posting of the form, and then redirect to the searchpage to enable the RenderMvcController to do the searching...
So I think you have most of the bits there, but not handling the request to the search page... but there are lots of different ways of doing this!
Got the gist and got it working following your code example, SurfaceController to render and post form. SufaceController action to redirect to RenderMvcController with searchTerm via RedirectToUmbracoPage(pageID, requestString)
RenderMvcController to do the number crunching and send results to view page.
Great Dibs! - can't think of an appropriate Arnie line from a film...
... but apparently he does inspirational quotes too:
"Strength does not come from winning. Your struggles develop your strengths. When you go through hardships and decide not to surrender, that is strength"
moving search functionality code to controller
Hi Umbraco Team
I am trying to move code from view to controller, learning how to make use of MVC in Umbraco. My goal is to create a partial view for the search box and submit button and a search results page that displays search results. Sounds simple, but to the life of me i cant get it to work via SufaceController or RenderMvcController. I keep getting errors in my code.
I have the partial search term form, this i would like to render on header and search results page.
This works fine : ) This is my Controller, named after my DocType in backoffice
This is my search results page, find.cshtml
The above code is a starting block for me to get the search results page rendering via direct access or via the search term form. The above code works as expected, search results page renders ok.
My next step is to make use of a custom model to hold title link and excerpt of search results from the search term and render them on the search results page.
My custom model is
Here is where i get stuck, i make a change to my search results page Find.cshtml to inherit my custom model.
This causes following error
passing the custom model to the controller makes no difference. Changing my controller to use RenderMvcController causes The name 'CurrentUmbracoPage' does not exist in the current context.
Im not sure how i can make my custom model fit in my current code to display search results on my search results page
Anybody able to assist or advise where im going wrong ?
Thanks Dibs
Hi Dibs
There are different ways of making this work.
Generally the rule of thumb for Umbraco is to use a SurfaceController that has the job of handling a 'post back' from a form - and also for convenient ChildActions for rendering a PartialView inside your Umbraco template, eg to present the form.
However, you would typically use a RenderMvcController to handle the rendering of content for a request.
Therefore in this kind of pattern you often end up with two Controllers, one a SurfaceController that has a child action that Renders the form, and an Action that handles the postback from the form - checks validation etc
but if the form posting back validates then the SurfaceController would usually redirect to a GetRequest to a RenderMvcController that has the job of performing the search, and passing a custom model to the view to display the results.
So if your Search Results Page has Document Type 'SearchPage'
Create a controller called 'SearchPageController' that inherits from RenderMvcController
Then your view can inherit this custom model
You can render your search form either directly from a partial:
or via a child action
@Html.Action("RenderSearchForm","SearchFormSurface")
and have a property on your custom model determining if there are search results
And then your SurfaceController could look something like this:
so basically all it does is validate the posting of the form, and then redirect to the searchpage to enable the RenderMvcController to do the searching...
So I think you have most of the bits there, but not handling the request to the search page... but there are lots of different ways of doing this!
regards
Marc
Hi Marc thanks for reply
I get the gist of what your saying, i'll give it a go : )
Dibs P.S as Arnie would say 'i'll be back'
Cheers Marc
Got the gist and got it working following your code example, SurfaceController to render and post form. SufaceController action to redirect to RenderMvcController with searchTerm via RedirectToUmbracoPage(pageID, requestString)
RenderMvcController to do the number crunching and send results to view page.
Dibs : )
Great Dibs! - can't think of an appropriate Arnie line from a film...
... but apparently he does inspirational quotes too:
"Strength does not come from winning. Your struggles develop your strengths. When you go through hardships and decide not to surrender, that is strength"
not as snappy as
"consider that a divorce"
though :-P
regards
Marc
is working on a reply...