In Umbraco 6.1.1 MVC 4, how can I send a form message back to the surface controller using a model that inherits from Umbraco RenderModel?

Scenario:

I create a site in Umbraco 6 with MVC - I am pretty new to Umbraco, but I have done everything until now, following the tutorials, etc., and for the most part everything works beautifully.

So, I have a "contact us" form, built as a partial view, displayed using the following code:

@using (Html.BeginUmbracoForm("SendEmail", "ContactFormSurface")) { 

which returns to my ContactFormSurfaceController:

 public class ContactFormSurfaceController : Umbraco.Web.Mvc.SurfaceController { [HttpPost] public ActionResult SendEmail(ContactFormModel model) { 

Now my ContactFormModel is inherited from the Umbraco RenderModel, and I am "capturing" the route to view "Contact Us" in a separate ContactFormController:

 public class ContactFormController : RenderMvcController { // // GET: /Contact-us/ public override ActionResult Index(RenderModel model) { var contactFormModel = new ContactFormModel(model); return CurrentTemplate(contactFormModel); } 

I want to have flexible headers and the text of a submit button in a contact form based on the contents of Umbraco. My ContactFormModel accepts a RenderModel in this constructor so that it has access to the main content of Umbraco:

 public class ContactFormModel : RenderModel { #region Ctr public ContactFormModel(RenderModel model) : base(model.Content, model.CurrentCulture) {} #endregion #region Contact Form Fields [Display(Name = "Your Name")] [Required] public string Name { get; set; } 

Problem:

When the form returns back to my SendEmail method on the surface controller, an attempt is made to instantiate a new ContactFormModel, and I get YSOD with the following exception:

There is no constructor without parameters for this object.

My first thought was, normally, I will put the constructor without parameters, since I really do not need access to the Umbraco content in the SendEmail surface controller method, I want this to be only during the initial rendering of the view. But this is not so simple, since the base RenderModel requires the IPublishedContent to pass a constructor to it. I just skipped null as well:

 public ContactFormModel() :base(new DynamicPublishedContent(null)) {} 

but this leads to the exception "Value cannot be null."

Then I tried changing my Umbraco form expression to:

 @using (Html.BeginUmbracoForm("SendEmail", "ContactFormSurface", new {model = @Model})) 

to make sure ContactFormModel is passed to the view, sent back to the surface controller. This goes past YSOD, but in the SendEmail method of the surface controller, "model" is null.

So, I do not understand a little:

  • Why is there an attempt to call a constructor without parameters on my ContactFormModel in the first place? Why is my ContactFormModel from a view that is not only available in the surface controller method, since this is what I pointed out?

  • When I explicitly add a model to the route values ​​for the post form, why did it go through zero?

It seems like there should be a simple solution to this, and maybe I missed something fundamental. When searching forums, there are many examples of route interception and inheritance with RenderModel, as well as the use of a custom model and surface controller to process a form message, but not two combined things when a custom model is inherited from RenderModel.

If I cannot find a solution to this issue, I will have to resort to non-inheritance from RenderModel and, therefore, not to allow editable content in the form of a contact, which seems to defeat the Umbraco object. Or create another model, exclusively for use with a surface controller, which does not inherit from RenderModel but duplicates all the fields in my ContactFormModel, which would be crazy!

Thanks for any ideas or advice.

+6
source share
1 answer

Well, I had no answers to this question, but now I can answer it myself. Perhaps this was fundamental oversight, but not that obvious imho, and information on the Umbraco forum, etc. On inheritance from RenderModel is pretty limited.

Essentially, the answer, like my first instinct, is to solve the original exception, “Without a constructor without parameters defined for this object”, by providing a constructor without paramedia. The difficulty lies in developing what to put inside the constructor without parameters for my model, since it inherits from the Umbraco RenderModel, for which an IPublishedContent instance is passed to its constructor.

Fortunately, when I was browsing the site, I got this post on the Umbraco forum: http://our.umbraco.org/forum/developers/api-questions/40754-Getting-CurrentPage-from-SurfaceController .

What I did not quite understand is how the current page / view of information is transmitted through the Umbraco Context. So, as in the previous post, I created a couple of new constructors for my user model:

  public ContactFormModel() : this(new UmbracoHelper(UmbracoContext.Current).TypedContent(UmbracoContext.Current.PageId)) {} public ContactFormModel(IPublishedContent content) : base(content) {} 

With their help, when I now submit the form back to my Surface Controller method, as if by magic, my ContactFormModel is filled with all the data entered.

+13
source

Source: https://habr.com/ru/post/948049/


All Articles