Passing my own data types to a view

Topics: General, Troubleshooting, Writing modules
Jun 27, 2012 at 10:16 AM
Edited Jun 27, 2012 at 10:19 AM

Hi Guys,

I've written a small system in MVC that allows users to manage their profiles and I need to port it into an Orchard module. The user data is stored in a bespoke database and I am trying to pass it to the view from the driver as shown below. It fails because Orchard is wrapping my data in a IShapeProxy86b653.. and my view is expecting an IEnumerable<PerkinsExtendedProfiles.Models.User>. Am I going about this the right way and, if so, how do I pass my data to the strongly typed view?

            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                var users = db.Users.Include(u => u.Company).ToList();


                return ContentShape("Parts_DistributorsIndex", () => shapeHelper.Parts_DistributorsIndex(
                        Model: users
                    ));
            }

Many thanks

Jun 27, 2012 at 11:10 AM
Edited Jun 27, 2012 at 11:12 AM

I figured it out..

I can access my model like this in my view:

Model.Model as IEnumerable<PerkinsExtendedProfiles.Models.User>
Developer
Jun 27, 2012 at 11:14 AM

If you change your view to expect a dynamic, then you can access your users like so:

@model dynamic
@{

   var users = (IEnumerable<PerkinsExtendedProfiles.Models.User>)Model.Model;

}

The way this works is that the shape you created in your driver will be the model of your view. In your sample you're createing a Model property on this shape (you should probably rename that to "Users")

 

Developer
Jun 27, 2012 at 11:15 AM
JoeyJackson wrote:

I figured it out..

I can access my model like this in my view:

Model.Model as IEnumerable<PerkinsExtendedProfiles.Models.User>



Nice. Although you may want to rename the "Model" property to "Users"

Jun 27, 2012 at 12:47 PM

Many thanks for your reply sfmskywalker, looks like I just beat you to it but it's much appreciated anyway.

Good idea, I will rename it now.

Developer
Jun 27, 2012 at 2:45 PM

No problem, it's great you figured it out yourself.

Jun 27, 2012 at 5:22 PM

The only problem I have found with this solution is all of the 'For' html helpers stop working due to the Model type changing. Do you happen to know of any work arounds?

Thanks

 

        
@Html.LabelFor(model => model.Surname) @Html.EditorFor(model => model.Surname) @Html.ValidationMessageFor(model => model.Surname)

Developer
Jun 27, 2012 at 5:38 PM

I'd be happy to know this too... This is particularly problematic when overriding editor shapes with the Shape Place attribute, where the shape then gets the original statically typed model as Model.Model.

Developer
Jun 27, 2012 at 7:31 PM

Why not cast it to the "real" type, e.g. User:

@model dynamic
@{
   var user = (User)Model;
}
@Html.LabelFor(model => user.Surname)
@Html.EditorFor(model => user.Surname)
@Html.ValidationMessageFor(model => user.Surname)

 

Jun 28, 2012 at 9:04 AM

That works perfectly, thanks. I still haven't really got my head around the 'For' methods.

Developer
Jun 28, 2012 at 11:19 AM

@sfmskywalker: Excellent, thanks! How could I missed that till now.

There is a slight issue though when overriding editor templates with the mentioned Shape attribute. Namely, the field name prefix won't be used, as it isn't automatically set, in contrary to normal editor templates. This can be easily overcome by setting it explicitly. For example, here is an override for the Text field editor template:

@{
    Html.ViewContext.ViewData.TemplateInfo.HtmlFieldPrefix = Model.Prefix;
    var viewModel = (Orchard.Core.Common.ViewModels.TextFieldDriverViewModel)Model.Model;
}      

<fieldset>
    @if (String.IsNullOrWhiteSpace(viewModel.Settings.Flavor)) {
        @Html.TextBox("Text", viewModel.Text, new { @class = "text" })
    }
    else {
        @Display.Body_Editor(Text: viewModel.Text, EditorFlavor: viewModel.Settings.Flavor)
    }
    <span class="hint">@viewModel.Settings.Hint</span>
</fieldset>

I haven't used the *For helpers, as they also include "viewModel" in the field name.

Developer
Jun 28, 2012 at 2:01 PM

Thanks Piedone. I haven't really used Shape attributes much, so this great to know! That's an interesing way of using Shape attributes. Do you maybe have some sample code somewhere demonstrating how you use the Shape methods (decorated with the Shape attribute) and use that as an editor template? Or should I compare it with the way one could use the UIHint attribute to designate the property to a specific editor template?

Jun 28, 2012 at 2:12 PM

 

http://chrisbower.com/2011/02/15/orchard-shape-wizardry/

Aug 23, 2013 at 9:35 AM
Hi, I am trying to implement something similar to this but upon POSTing back to the Driver I can't seem to update the model.