How to access different Models across shapes?

Topics: Core, Troubleshooting, Writing themes
Dec 13, 2012 at 8:36 AM

I have a ContentType called "Project" implementing CommonPart. I need to access it's CommonPart Id to create a direct link to it's edit page "Admin/Contents/Edit/##".

If I try to access it from the Project.cshtml shape it is easy to get:

    dynamic contentItem = Model.ContentItem;
    var contentId = contentItem.CommonPart.Id;

 

Now, I need to have that CommonPart.Id accessible via another shape User.cshtml. I do not seem to find a way to access the Project Model to retrieve that simple Id; the previous code obviously returns null.

Any thoughts on how to implement that?

Dec 13, 2012 at 10:55 AM

You will need to come up with a way to get a reference to the Project content item. Inside the User.cshtml template, the view model is the User shape. Now I obviously don't know anything about your object model, but if you somehow have a link between Projects and Users, you could for example implement an IShapeTableProvider, describing the User shape, and enriching that shape with a Project content item, which will then be accessible from the User.cshtml shape.

Dec 13, 2012 at 5:30 PM
Edited Dec 13, 2012 at 5:31 PM

Ok, IShapeTableProvider sound good. But is there any simpler solution?

I am trying to avoid the need of any coding outside the View itself given that it is such a simple value that I need. Is there any way that I can just pass this value as a parameter when adding the Shape to Layout? My current Layout displays the following:

 

@{
    
Model.Header.Add(New.User(),"1"); //can I pass a parameter here?

Model.Header.Add(New.SearchForm(), "2");
} <!--start: Header -->

 

What could be nice is if I could do something similar to the following, it would save me lots of coding. Is this possible somehow?

Model.Header.Add(New.User([pass value here]), "1");

 

Or maybe somehow access the content item through WorkContext in one line as with settings in the following code?

var userCanRegister = WorkContext.CurrentSite.As<Orchard.Users.Models.RegistrationSettingsPart>().UsersCanRegister;
Dec 13, 2012 at 6:18 PM

yes, you can already do that. "Model.Header.Add(New.User(SomeProperty: "jogarriot"), "1")"

Now in the User.cshtml you can access the property through the Model:

 

@model dynamic

@{

    string someProperty = Model.SomeProperty as string;

}

Dec 13, 2012 at 7:43 PM

I'm almost getting there, but just realized I wasn't considering the structuring of the shapes.

Basically what I want is to mimic the "Edit" ActionLink that comes with Content Control Wrapper module, and have it appear in the User shape instead of the Content-Project shape; I need the user to see for navigation menu the options Edit Project, New Project, etc. I realized the passing of arguments through Models doesn't solve this unless I am able to access the Project model from Layout, which I haven't been able to.

My views structure looks like this:

Layout   --> User
              --> Project  (CommontPart.Id)

Is there any way I can access the Project.CommonPart.Id from Layout or User, or do I forcefully need IShapeTableProvider?

Dec 13, 2012 at 8:05 PM

Either pass the CommonPart.Id to both the User and Project shapes, if that's possible, or use IShapeTableProvider. If you can get the data you need at IShapeTableProvider just do it that way. Why resist the method that's been suggested? 

Dec 13, 2012 at 8:17 PM

I was resisting since I haven't built a IShapeTableProvider just yet and my brain is still struggling to make sense of this dynamic environment. I'll take the IShapeTableProvider path, thank you guys!