Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • iand123 23 posts 53 karma points
    Jun 17, 2017 @ 08:23
    iand123
    0

    SurfaceController empty model on post

    Hi

    Ive got an umbraco page which is using a childaction partial to render a form. This is working fine but the model passed it always empty. Can someone help

    Here is what i have

    Umbraco Page:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = "Master.cshtml";
    }
    
    @Html.Partial("~/Views/Apply/Index.cshtml", new ApplyViewModel())
    

    Partial view:

    @inherits UmbracoViewPage<ApplyViewModel>
    
    @using (Html.BeginUmbracoForm<ApplyController>("HandleApplyForm", FormMethod.Post, new {@enctype = "multipart/form-data"}))
                {
                    @Html.ValidationSummary(true)
                    @Html.AntiForgeryToken()
                    <div class="row">
                        <div class="col-sm-6">
                            <div class="form-group">
                                @Html.LabelFor(model => model.Name)
                                @Html.TextBoxFor(model => model.Name, new { placeholder = "Your Name", @class = "form-control" })
                                @Html.ValidationMessageFor(model => model.Name)
                            </div>
                        </div>
                        <div class="col-sm-6">
                            <div class="form-group">
                                @Html.LabelFor(model => model.Telephone)
                                @Html.TextBoxFor(model => model.Telephone, new { placeholder = "Your Telephone Number", @class = "form-control" })
                                @Html.ValidationMessageFor(model => model.Telephone)
                            </div>
                        </div>
                        <div class="col-sm-6">
                            <div class="form-group">
                                @Html.LabelFor(model => model.Email)
                                @Html.TextBoxFor(model => model.Email, new { placeholder = "Your Email Address", @class = "form-control" })
                                @Html.ValidationMessageFor(model => model.Email)
                            </div>
                        </div>
                        <div class="col-sm-12">
                            <div class="form-group">
                                <label>Upload your CV (Microsoft Word doc, docx, pdf files under 1MB size only)</label>
                                <input id="CV" name="CV" type="file" class="form-control"/>
                            </div>
                        </div>
                        <div class="col-sm-12">
                            <div class="form-group">
                                @Html.LabelFor(model => model.Message)
                                @Html.TextAreaFor(model => model.Message, new { placeholder = "Your Message", @class = "form-control" })
                                @Html.ValidationMessageFor(model => model.Message)
    
                            </div>
                        </div>
                        <div class="col-sm-12 text-center">
                            <button type="submit" class="btn btn-primary"><i class="fa fa-envelope-o"></i> Apply</button>
                        </div>
                    </div>
                }
    

    Controller:

     [ChildActionOnly]
        public ActionResult Index()
        {
            return PartialView();
        }
    
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult HandleApplyForm(ApplyViewModel model)
        {
            //Check if the dat posted is valid (All required's & email set in email field)
            if (!ModelState.IsValid)
            {
                //Not valid - so lets return the user back to the view with the data they entered still prepopulated
                TempData.Add("MyModel", model);
                return RedirectToCurrentUmbracoPage();
            }
    

    ViewModel:

    public class ApplyViewModel : RenderModel
    {
        public ApplyViewModel() : base(UmbracoContext.Current.PublishedContentRequest.PublishedContent, UmbracoContext.Current.PublishedContentRequest.Culture)
    {
    
        }
    
        [Required]
        public string Name;
    
        public string Email;
    
        public string Telephone;
    
        [Required]
        public string Vacancy;
    
        [Required] public string Message;
    
        public string Url;
    
        public HttpPostedFileBase CV { get; set; }
    
    }
    

    The model properties are always null (apart from the CV file upload but assuming it gets this from the request object). Can someone help me please? Been tearing my hair out with this since 6am this morning

  • iand123 23 posts 53 karma points
    Jun 17, 2017 @ 09:35
    iand123
    0

    To add a bit more context

    The site is for a recruitment agency. The initial page is populated with data from Umbraco, i have created it from a document type and created content from the umbraco backend (has then details of the job, decription, salary etc)

    I am trying to render the partial view of the apply form to the bottom of these pages. Is this where I am going wrong? WOuld i be better directing to a new page to apply or can i do it from the same page?

  • Marc Goodson 2138 posts 14321 karma points MVP 8x c-trib
    Jun 17, 2017 @ 17:43
    Marc Goodson
    0

    Hi iand123

    When you have a validation error...

    return CurrentUmbracoPage();

    this will return to your page and present the form with the Modelstate intact, eg with validation errors for the user to correct.

    returning 'RedirectToCurrentUmbracoPage()' is generally used when the form is submitted correctly, has no errors, you've sent an email or inserted the form details into a db and you want to clear the modelstate and return the user back to the page with the form reset - perhaps adding a message to the TempData to say thanks...

    but no need to add the model to the TempData dictionary, returning CurrentUmbracoPage will persist the model for you.

    regards

    Marc

  • iand123 23 posts 53 karma points
    Jun 17, 2017 @ 18:26
    iand123
    0

    Hi Marc

    Thanks for the reply. I'll implement as you say thanks for that, however the model is always null when i hit the surface controller (apart from the CV file that is uploaded). Any ideas why that might be?

  • Marc Goodson 2138 posts 14321 karma points MVP 8x c-trib
    Jun 17, 2017 @ 21:47
    Marc Goodson
    0

    Hi iand123

    I think your ApplyViewModel shouldn't inherit RenderModel

    It should just be a POCO class. containing the properties of the form you are posting.

    Your Surface Controller action should receive them, you process the application then redirect the user back to the page - presumalbly you are checking in the rendering of the page whether the logged in user has already applied, so after the redirect, this logic will click in, and you won't display the form again, but maybe add a message to ViewBag to temporarily say 'thanks for applying'

    There is another technique in Umbraco called Route Hijacking, where you hijack a request for a page, and run it through your own RenderMvcController, in this context you can create a rich model to use in your templates, and your model would need to inherit RenderModel.

    But to just handle a form post it doesn't.

    If that makes sense!

    regards

    Marc

  • iand123 23 posts 53 karma points
    Jun 19, 2017 @ 12:30
    iand123
    0

    Hi Marc

    I've removed the inheritance now, id seen a few examples of this and saw some had it but its now removed.

    Can someone link me to a good example or guide of how this should work please? I started from scratch and re-defined a very basic model to see if I could get this working and I had the same problem (model properties are always null regardless of what was posted).

    If anyone has any other ideas or pointers as to what might be causing this i'd love to hear them!

  • Marc Goodson 2138 posts 14321 karma points MVP 8x c-trib
    Jun 19, 2017 @ 20:06
    Marc Goodson
    100

    Hi iand123

    Think the problem likes in your model, you don't have getters and setters defined for your properties:

    Try:

    public class ApplyViewModel
    {
    
    [Required]
    public string Name { get; set; }
    
    public string Email { get; set; }
    
    public string Telephone { get; set; }
    
    [Required]
    public string Vacancy { get; set; }
    
    [Required]
    public string Message { get; set; }
    
    public string Url { get; set; }
    
    public IEnumerable<HttpPostedFileBase> CV { get; set; }
    }
    

    it should allow the model binding to work.

    (also you don't have a field for vacancy on the form,,, hidden field?)

    regards

    Marc

  • iand123 23 posts 53 karma points
    Jun 19, 2017 @ 20:16
    iand123
    0

    I worked this out (when I say worked out stumbled across it when I saw some posts about MVC Model binding failing) and forgot to post. Thanks for the help though

  • Marc Goodson 2138 posts 14321 karma points MVP 8x c-trib
    Jun 19, 2017 @ 20:28
    Marc Goodson
    0

    No problem, sorry I didn't spot it earlier! - I built it out in visual studio to see what was going wrong, and as I typed the properties... I think the recruitment scenario is a good example for a surface controller tutorial though.

    Hope the rest of it goes well.

    regards

    Marc

  • iand123 23 posts 53 karma points
    Jun 19, 2017 @ 20:37
    iand123
    0

    Yeah it's a good idea; I'll try and get a blog up about it

Please Sign in or register to post replies

Write your reply to:

Draft