Don't miss out Virtual Happy Hour this Friday (April 26).

Try our conversational search powered by Generative AI!

Generic way of setting up my MVC forms in Episerver 8

Vote:
 

Guys and girls,

I have a page (pagetype: Education). There is a lot of information on this page and 1 item on there is a form to register for a brochure.

Now my whole setup is that i dont have to create Controllers and Index views for all my pagetypes.  So i have a DefaultPageController which just creates a ViewModel with my currentPage and returns the corresponding view (with the samen name as the pagetype).  Right?

[TemplateDescriptor(Inherited = true)]
    public class DefaultPageController : PageControllerBase
    {
        public ViewResult Index(SitePageData currentPage)
        {
            var model = CreateModel(currentPage);
            return View(string.Format("~/Views/Pages/{0}.cshtml", currentPage.GetOriginalType().Name), model);
        }
        private static IPageViewModel CreateModel(SitePageData page)
        {
            Type viewModelType = typeof(PageViewModel<>).MakeGenericType(page.GetOriginalType());
            return (IPageViewModel)Activator.CreateInstance(viewModelType, page);
        }
    }

i have a BrochureForm class which will be used as the model for my form.

public class BrochureForm 
    {
        [Required(ErrorMessage = "name is mandatory")]
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
        public string Comment { get; set; }
}

I have a partialView with my BrochureForm

@model Website.Models.Forms.BrochureForm
@using EPiServer.Core;
@{
    Layout = null;
    HtmlHelper.UnobtrusiveJavaScriptEnabled = true;
    HtmlHelper.ClientValidationEnabled = true;
}

Brochure

using (Html.BeginForm(null, null, FormMethod.Post)) { @Html.ValidationSummary() @Html.AntiForgeryToken() @Html.EditorForModel() } }

THE PROBLEMS:

So in my view (Education) where i have all my other views and elements on the page

  • How can i properly call the BrochureForm partial.
  • I want the form not to completely postback, but give me the model (validated) back or success message. So i want it to be ajax enabled..  I' m very new to MVC so bear with me. I've read a lot and tried a lot of options but i want to clean and generic way of handling such forms where i can do whatever i want with the posted data within episerver context.
  • I have other forms which will do other stuff with the data, like posting it to a webservice, so i want it to be a simple generic solution which i can re-use in other form scenarios.

Does anyone have some code lying around or did something similar. All examples i found are just for complete postbacks, or just pages which contain a form (without any other stuff on it) etc.

Hope to get some more insight on the workings of MVC forms in an EPiServer context.

#121630
May 15, 2015 16:28
Vote:
 

I see few issues here. It's just my humble opinion. First, from personal experience, I would try to avoid over generalized page controllers. In your case it reminds me of scaffolding project from Microsft time ago (Dynamic Data). In every project I was working on we always ended up with some edge cases when you need to have something special about that page and how it's behaving or handling stuff.

Anyway back to your questions. First of all you will need to make a connection from page type to form it self. It could be property of the page type, it could be somehow configured more dynamically over settings somewhere (doesn't matter actually). Then in your page tempalte you may call @Html.Partial("BrochureForm", Model.Form). If you are looking for more generic way - then you may need to create probably your own Partial method overload - that will try to figure out name of the partial view out of model type. For instance - @Html.MyPartial(Model.Form) - this method would extract type from Model.Form and then based on that would try to find a template.

Next question is what to do with post backs (either they are made as ordinary post backs, ajax calls, webapi calls, doesn't matter actually). Who is going to handle submit of the form and how? Depending on form action you are rendering in form itself, ajax calls and webapi - should be straight forward. When it comes to page postbacks - it may get tricky. How to forward posted request to the handler of the form action. And actually before that - who is the handler of the form submit? Do you have a controller that may handle, does it happen in page controller?

Anyway if you take one step back, this reminds me of just ordinary page types, maybe single generic controller (if you can survive witht that), templates for the pages and content area, where you could just drop any block you need. Single form may be represented as block, if will has it's own template registration entry (RenderTemplateRepository), EPiServer will make sure to pick up correct templates while rendering ContentArea. Then EPiServer may even come and help you with handling page postbacks and delegating handling of the data submit to block's controller if found any..

#121633
May 16, 2015 7:44
Vote:
 

Hi Valdis,

Thanks for your reply.

Yea i was wondering if the generalized page controller would come bite me in de ass one day :-). But i guess (i have to test) that if i create a pagecontroller (for my pagetype) and also the Index view then it will first check if that exists before going to the default (generalized) page controller. But i have to test it. 

I understand what you are trying to say about the page type to form itself. I think i can figure something out there. 

Now your last 2 paragraphs are interesting. I was trying to make a webapi where my form would submit to but i think my knowledge of that isn't up to par yet. 

Is there an example out there that you know of, where i could get some practical insight into how to do this. 

Also you mentioned about representing a form  as a Block which could be added in a ContentArea. I didnt really understand the template registration thingy.. Is there a blog post about this somewhere?

I think i'm getting there but just some push in the right direction about the last 2 parts and i will find my way. 

#121634
May 16, 2015 14:49
Vote:
 

Hi,

If you will have a controller that is inheriting from PageController<YourSpecificPageType> - EPiServer will invoke that controller instead of default one decorated with [TemplateDescriptor] attribute.

To post form to webapi endpoint is actually pretty easy. This sample is valid if you have Angular around:

angular.module('Module1')
    .controller('Controller1', [
        '$scope', '$http', 'appConfig', function($scope, $http, appConfig) {

            var vm = this;

            var request,
                url = appConfig.apiPath + 'submit-new-form',
                params = { id: vm.number, subject: vm.subject };

            request = $http.post(url, params);

            request.then(function(response) { ... });
        }]);

`appConfig` is just a container for application wide config settings initialized somewhere down the angular pipeline.

If you don't have angular, jQuery syntax for submit is somewhere quite similar.

Answering about content area and template registration process - you may refer to SDK documentation on what happends underneath. Also Johan wrote nice article about shared blocks and IContent: http://world.episerver.com/blogs/Johan-Bjornfot/Dates1/2012/11/Shared-blocks--IContent/

#121635
May 16, 2015 15:33
Vote:
 

thanks Valdis.. i will dive into this... your help is appreciated.

#121636
May 16, 2015 15:39
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.