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" />
}
@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.
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):
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
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?
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:
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.
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...
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.
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:
The Partial View _FormAjax.cshtml looks like this:
Partial View Offices.cshtml:
Look at this line:
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:
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:
"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.
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):
Your code in the view would then become:
And then in the parent view you would project to this model:
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.
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
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?
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:
And then in _FormAjax.cshtml:
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!
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:
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.
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:
In Forms.cshtml I call the partial _FormAjax like this
In _FormAjax.cshtml, I insert my dropdown like this:
_OfficesDropdown.cshtml looks like this:
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...
Whatever, it works, if it's possible to fix the LINQ query then I'll use that way... thx again.
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.
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
is working on a reply...