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 373 posts 2057 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 373 posts 2057 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 373 posts 2057 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

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies