Copied to clipboard

Flag this post as spam?

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


  • firepol 125 posts 173 karma points
    Jun 11, 2013 @ 16:15
    firepol
    0

    Model.Content not available in Partial View (MyModel, not RenderModel)

    Hi,

    I'm trying to understand how to use MVC in umbraco and here my problem:

    I have a Template for a document type called Form.

    I have a document type called "Office". In my content tree, under my node for the form, I added different office children. The idea is to create a form with a dropdown menu containing all the office names and as value a special office id. I use the office document type also to create a page for all offices (office name, address, picture etc.)

    Contact Form
    -Office 1
    -Office 2
    -Office 3
    -...

    The Form.cshtml view looks like this:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @{
        Layout = null;
    }
    
    @Html.Partial("_FormAjax", new MySite.Models.FormModel())


    The Partial View _FormAjax.cshtml looks like this:

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<TranscorAstra.Website.Models.FormModel>
    @{
        Layout = null;
    }
    
    @using(Html.BeginUmbracoForm("Contact", "FormSurface"))
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary()    
    
        @*Here I would like to add an option for each office*@
    
        @Html.Partial("Offices", new global::Umbraco.Web.Models.RenderModel(Model.Content, Model.CurrentCulture)) 
    
        @Html.EditorForModel()
    
        <input type="submit" value="Send" />  
    }


    Partial View Offices.cshtml:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    
    @using umbraco.presentation.nodeFactory
    @using umbraco.cms.businesslogic.media
    
    <select id="ddOffices">
    @foreach (var page in Model.Content.Children.Where(x => x.IsVisible() && x.DocumentTypeAlias == "Office"))
    {
        <option value="@page.Id">@page.Name</option>
    }
    </select>

    Look at this line:

    @Html.Partial("Offices", new global::Umbraco.Web.Models.RenderModel(Model.Content, Model.CurrentCulture)) 

    The problem here is that Model.Content doesn't exist in that context*. I can't call the Offices partial like that.

    I tried also:

    @Html.Partial("Offices")

    but it doesn't work either: by not specifying the model the FormModel is passed by default (why?) and at the runtime will come an error complaining that it's not a RenderModel, but a FormModel.

    *I tried to follow the Partial Views documentation: here it says it should work...

    In the documentation it's written: 

    @inherits Umbraco.Web.Mvc.UmbracoViewPage

    "By inheriting from this view, you'll have instant access to those handy properties and have your view created with a strongly typed custom model."

    Any ideas how I should proceed to correctly populate the dropdown? Any approach is welcome, it must just work... Thank you.

  • Andy Butland 422 posts 2334 karma points MVP 4x hq c-trib
    Jun 12, 2013 @ 14:03
    Andy Butland
    0

    Couple of thoughts...

    First is probably obvious, but just in case - do you need the Offices list as a partial?  If not you can just place this logic in the _FormAjax view which would mean you have the references you need.

    If you are doing this for re-use though, perhaps make a custom view model for your Offices partial - e.g. a simple class with two properties - Id and Name - and then at the top of the Offices.cshtml file put (instead of @inherits):

    @model IEnumerable<TranscorAstra.Website.Models.OfficeFormModel>

    Your code in the view would then become:

    @foreach(var office in Model)
    {
       
    <option value="@office.Id">@office.Name</option>
    }

    And then in the parent view you would project to this model:

    @Html.Partial("Offices",Model.Content.Children.Where(x => x.IsVisible()&& x.DocumentTypeAlias=="Office")
    .ToList()
    .Select(x => new OfficeFormModel { Id = x.Id, Name = x.Name
    ))

    I've almost certainly got something wrong in the syntax above as haven't tried it directly, but think should work and explain the idea at least.

  • firepol 125 posts 173 karma points
    Jun 12, 2013 @ 15:27
    firepol
    0

    Hi Andy,

    the problem is that in the parent view (_FormAjax.cshtml), Model.Content doesn't work. Intellisense gives me already an error for that. This is caused because, to generate my form and have all the validation I need to use the

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<MySite.Models.FormModel>

    The problem is that "Model" is an instance of my "FormModel" and my FormModel has no .Content... thus Model.Content gives an error. How can I get the actual "IPublishedContent" in the partial view?

  • Andy Butland 422 posts 2334 karma points MVP 4x hq c-trib
    Jun 12, 2013 @ 22:19
    Andy Butland
    0

    I see what you mean.  Because you are inheriting from UmbracoViewPage though you should get access to the Umbraco helper using @Umbraco and hence could access @Umbraco.TypedContent(id)?  You need to get the id of the current page, but if you can do that the rest of your statement to get the child offices should work.

    Another way - with reference to my suggestion above - might be to add IEnumerable<TranscorAstra.Website.Models.OfficeFormModel> as a property of your top level FormModel.  Then in Forms.cshtml - where you do have reference to the Umbraco RenderModel you could do:

    @Html.Partial("_FormAjax",newMySite.Models.FormModel { Offices = Model.Content.Children.Where(x => x.IsVisible()&& x.DocumentTypeAlias=="Office")} )

    And then in _FormAjax.cshtml:

    @Html.Partial("Offices",Model.Offices)

    And then then define the model for Offices.cshtml as I suggested above.

    Hope that helps you get on track... as you can probably tell I'm finding my way with all this myself!

  • firepol 125 posts 173 karma points
    Jun 13, 2013 @ 18:17
    firepol
    0

    Andy, sorry I didn't get the hint to create an OfficeFormModel (OfficeModel).

    I tried your initial suggestion and created the OfficeModel. In my FormAjax.cshtml I added the code you suggested me:

    @Html.Partial("Offices", Model.Content.Children.Where(x => x.IsVisible() && x.DocumentTypeAlias=="Office")
     .ToList()
     .Select(x => new OfficeModel { Id = x.Id, Name = x.Name))

    Here I think there is a LINQ issue, because I get this error pointing to the ".Select" line: Cannot convert lambda expression to type 'string' because it is not a delegate type.

    I tried to put ".ToList()" in the end, or so add ".ToString()" after x.Id and x.Name but no way, I always get that error. I'm not super experienced in LINQ and I don't know how to fix this... did you try this code in your environment or you coded the answer before testing it? ;)

    No, seriously. I'm close to the solution, I feel it, but this little error is blocking me at the moment... any ideas are appreciated, thx again.

  • firepol 125 posts 173 karma points
    Jun 13, 2013 @ 18:41
    firepol
    1

    Ok you know what, I found a solution, ok I consider it quite ugly, but since the above is not working, I think it's quite ok.

    In my FormModel I added this property:

    public RenderModel UmbracoModel { get; set; }

    In Forms.cshtml I call the partial _FormAjax like this

    @Html.Partial("_FormAjax", new MySite.Models.FormModel { UmbracoModel = Model })

    In _FormAjax.cshtml, I insert my dropdown like this:

    @Html.Partial("_OfficesDropdown", new global::Umbraco.Web.Models.RenderModel(Model.UmbracoModel.Content, Model.UmbracoModel.CurrentCulture))

    _OfficesDropdown.cshtml looks like this:

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    
    @using umbraco.presentation.nodeFactory
    @using umbraco.cms.businesslogic.media
    
    <select id="ddOffices">
    @foreach (var page in Model.Content.Children.Where(x => x.IsVisible() && x.DocumentTypeAlias == "Office"))
    {
        <option value="@page.Id">@page.Name</option>
    }
    </select>

    So I have to pass the RenderModel from the beginning, else it seems to me that it gets simply lost, no way to retrieve it in a partial... which is what I consider a bit dirty. As I initially wrote, I was expecting (also by reading the umbraco documentation I initially linked) that by using this line in _FormAjax I could at least save 1 time this process of passing the initial RenderModel down to the partials...

    @inherits Umbraco.Web.Mvc.UmbracoViewPage<MySite.Models.FormModel>

    Whatever, it works, if it's possible to fix the LINQ query then I'll use that way... thx again.

  • Andy Butland 422 posts 2334 karma points MVP 4x hq c-trib
    Jun 13, 2013 @ 22:02
    Andy Butland
    0

    Apart from a misused bracket - penultimate one should be } not ) - it does work OK for me in what I think is an analgous situation.  I read when Googling that message that you might be missing a using System.Linq - but actually I don't have that.  So not sure I'm afraid.  But glad you got a solution anyway.

  • firepol 125 posts 173 karma points
    Jun 14, 2013 @ 08:59
    firepol
    0

    Hei Andy, I corrected the braket,the syntax looks good at least for intellisense, really strange because I really wanted to try your solution.

    Asap I have some free time I will try to debug it, cheers

Please Sign in or register to post replies

Write your reply to:

Draft