widget creation

Topics: General, Writing modules
Feb 7, 2012 at 3:15 PM

I migrated a page done in MVC3 Razor using Routes.cs / HomeController etc. The page works fine in Orchard.
Now I created a Widget out of it which obviously gets created BUT it doesn't show the content i.e. the Cube.

? Is it possible if the Create method in migrations.cs is empty ?
? what am I missing here ?

Thanks for your time, ed

I used below Migrations.cs.

using System;
using System.Collections.Generic;
using System.Data;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Core.Contents.Extensions;
using Orchard.Data.Migration;
using Orchard.Indexing;


namespace ICube {
    public class Migrations : DataMigrationImpl {
        public int Create() {
            return 1;
        }
                
        public int UpdateFrom3() {
  ContentDefinitionManager.AlterPartDefinition("ICubePart",
    builder => builder.Attachable());
  return 4;
}
        public int UpdateFrom5() {
            // Create a new widget content type with ourICube
            ContentDefinitionManager.AlterTypeDefinition("ICubeWidget", cfg => cfg
                .WithPart("WidgetPart")
                .WithPart("ICubePart")
                .WithPart("CommonPart")
                .WithSetting("Stereotype", "Widget")
                .Creatable()
                .Indexed());
            return 6;
        }

    }
}

Coordinator
Feb 7, 2012 at 5:27 PM
Edited Feb 7, 2012 at 5:28 PM

Placement? Oh no, wait, the migration numbers need to be connected. UpdateFrom3 will never run because Create is only returning 1.

Feb 8, 2012 at 1:48 PM

thanks for returning ... well, I start to think that I'm having an issue with my system, or, .........   with myself !

I understand, that the migration always has to be "UpdateFromN (N being the last return value) and then: return N+1";
(I tried so many variations that I sent a screwd one, sorry).

I started from scratch several times with my ICube; using the HomeController.cs and a Routes.cs; this works just fine as a separate page.
HOWEVER, when trying to create the 'part' and in turn the 'widget' by adding first "UpdateFrom1 ... return 2" I'm NOT prompted to update my ICube feature! Neither do I get prompted when adding the "UpdateFrom2 ... return 3".

So I'm starting to think that I miss something fundamentally or do it in the wrong sequence ....

Any hint and your time is appreciated, ed  

using System;
using System.Collections.Generic;
using System.Data;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Core.Contents.Extensions;
using Orchard.Data.Migration;
using Orchard.Indexing;

namespace ICube {
    public class Migrations : DataMigrationImpl {

        public int Create() {
            return 1;
        }

        public int UpdateFrom1() {
         ContentDefinitionManager.AlterPartDefinition("ICubePart",
            builder => builder.Attachable());
         return 2;
        }

        public int UpdateFrom2() {
            // Create a new widget content type with ourICube
            ContentDefinitionManager.AlterTypeDefinition("ICubeWidget", cfg => cfg
                .WithPart("WidgetPart")
                .WithPart("ICubePart")
                .WithPart("CommonPart")
                .WithSetting("Stereotype", "Widget")
                .Creatable()
                .Indexed());
            return 3;
        }
    }
}

Coordinator
Feb 8, 2012 at 5:34 PM

Once a migration has run, the migration number is recorded in the database, so unless you go into the database and roll back the migration number manually, that particular migration will never run again.

Also, if you are using 1.x (not 1.3) then migrations are automatically executed without user intervention.

And of course, on all versions, when the module is first enabled, all migrations are run silently.

Feb 8, 2012 at 7:33 PM

thanks, that clarifies a lot; I was afraid changing that record could mess the system!? Now I can see the 'Content Part' and ' Content type'.

But now coming back to my original issue - not seeing my content (ICube) when applying the widget to a Zone.

You mentioned originally 'placement' could be the issue (below see my placement.info file). But might be another peace of info
could help: In Content Types I have 'ICube' with 'Create new ICube'; when clicking on  'Create new ICube' I get below error.
I'm afraid I still do something wrong when creating this widget.

? how should I set placement.info ? PS: I agree I need to learn more about this file!

thanks again for your patience, ed

Error:
Description: An unhandled exception occurred during the execution of the current web request.
Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:
Line 6:  <fieldset>
Line 7:      @Html.LabelFor(widget => widget.LayerId, T("Layer"))
Line 8:      @Html.DropDownListFor(widget => widget.LayerId, new SelectList(Model.AvailableLayers, "Id", "Name")) <=== error
Line 9:  </fieldset>
Line 10: <fieldset>
Source File: d:\MyWebSites\ASGB\Modules\Orchard.Widgets\Views\EditorTemplates\Parts.Widgets.WidgetPart.cshtml    Line: 8

<Placement>
    <Place Parts_ICube="Content:after"/>
</Placement>

Coordinator
Feb 8, 2012 at 8:51 PM

Are you seeing any problems with other widgets and other layers?

Feb 9, 2012 at 7:11 AM

To familiarize myself with this business I loaded the Bing.Maps feature - which works fine; i.e. I can apply it to any Zone in any page I want.
On my ICube feature, regardless on which page / Zone I want to apply the widget, I see the following difference when Checking 'Content' in the dashboard to compare Bing.Maps with ICube:

Content Parts: no difference
Content Types: no difference

Content Items:
AS the first item in 'Content Items' I have: 'ICube' and above 'Edit' (the rest of this row is empty). 'ICube' is the title I gave when adding the widget to my Zone.
When clicking 'edit' I'm directed to the 'edit widget' screen ( same screen I got when choosing the widget).

Another difference in Dashboard News:
I have an item 'ICube'. When clicking, I'm directed to the same screen as when clicking 'widget' in the dashboard!

As a novice, on my setup, I see three differences:
A) The 'create' in data migrations is empty; I guess this is correct because I do not use any DB here.
B) my View ICube.cshtml (created in MVC3 VS2010) is in the root of Modules/ICube/views. I.e. I do not have Modules/ICube/Views/parts/ICube.cshtml NOR Modules/ICube/Views/EditorTemplates/parts/ICube.cshtml.
Although, I added these directories and did a test with ICube.cshtml in both of them!
C) I do not use any drivers nor handlers!

to repeat myself; I really appreciate your help, ed

Coordinator
Feb 9, 2012 at 7:49 AM

If you don't use the DB, you don't need a migration at all.

I'm beginning to suspect you forgot placement.

Feb 9, 2012 at 8:18 AM

Here's a question ... if you're not using the DB, then what is ICubePart? Can you show us the code for the model, handler and driver?

Feb 9, 2012 at 10:51 AM

ICubePart:
I start to realize (learn) that ICubePart is only used in the context of a DB.
So I guess my ICubePart got generated because I used a .WithPart("ICubePart") in my migrations.cs. - it seems this is not needed or might even confuse Orchard!

As I said in my previous reply: I do NOT use whether a Model (no DB) NOR a Driver / Handler.

All I want is running my ICube.cshtml which I developed in MVC3 VS2010 to run under Orchard
(essentially these are some <img src="... statements and some jquery code)
This runs fine in Orchard using a 'Routes.cs' and 'HomeController.cs' file.

Now I would like to generate a 'widget' for this ICube which I can apply to any Zone!

PS: I'm more than happy to provide you with the complete ICube 'Module'; where could I send a .zip file!?

sorry for my ignorance, but thanks to a very good product, ed

Feb 9, 2012 at 11:46 AM

If you haven't got a driver or a handler then you're not generating a view. Drivers are used to emit shapes which map to .cshtml files (or can be rendered in code). You can also do this in handlers, but it's better to use a driver because otherwise you can't use Placement at all. You don't need a record for a content part but you still need to generate the view somewhere.

Feb 9, 2012 at 2:44 PM

well could you tell me how such a Driver would look like?!
I copied below Driver.cs from Bing.Maps and get below error (I know this is not professional and really just a guess).

! I must miss something substantial here !

.... need help i.e. more documentation and/or a sample ..., ed 

CS0246: The type or namespace name 'ICubePart' could not be found (are you missing a using directive or an assembly reference?)
PS: before I used the Driver I checked: I can see the ICubePart in 'Content parts'!

using Orchard;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;

namespace ICube.Drivers {
  public class ICubeDriver : ContentPartDriver<ICubePart> {
    protected override DriverResult Display(
        ICubePart part, string displayType, dynamic shapeHelper)
    {
      return ContentShape("Parts_ICube",
          () => shapeHelper.Parts_ICube(
       
        // ??????????????????
       
            );
    }
   //GET
    protected override DriverResult Editor(ICubePart part, dynamic shapeHelper)
    {
      return ContentShape("Parts_ICube_Edit",
          () => shapeHelper.EditorTemplate(
              TemplateName: "Parts/ICube",
              Model: part,
              Prefix: Prefix));
    }

    //POST
    protected override DriverResult Editor(
        ICubePart part, IUpdateModel updater, dynamic shapeHelper)
    {
      updater.TryUpdateModel(part, Prefix, null, null);
      return Editor(part, shapeHelper);
    }
  }
}

Feb 9, 2012 at 3:15 PM

In which namespace is ICubePart? If not in ICube.Drivers, you would need to add a using directive, like "using ICube.Models;"

Feb 9, 2012 at 5:40 PM

there is obviously a blackout on my side.

As I said I do NOT have a Model, hence I do Not have a namespace ICube.models (Nor do I have a Driver / Handler). So Randompete told me that I need to define a driver (see his last reply).

My only reference to ICubePart is in 'migrations.cs' (see below; and full code in earlier thread replies).

 public int UpdateFrom1() {
ContentDefinitionManager.AlterPartDefinition("ICubePart",
builder => builder.Attachable());
return 2;
}

My understandig is that I would define a 
"public class ICubePart : ContentPart<ICubeRecord> { .... "
 in the model .... if I would have a DB needing a Model.cs.

Again: I'm happy to .zip you my ICube Module ... might be that would be more productive!

I would appreciate if you would once read the complete thread to see where I'm strugglin, thanks!
thanks for your time, ed

Feb 9, 2012 at 6:21 PM

Yes, but you're referring to ICubePart in your ICubeDriver.

I'm not sure if there is any more cool way to do this, but you could create an empty ContentPart which would make it possible to use your driver with that code.

Coordinator
Feb 9, 2012 at 6:33 PM

Your driver looks fine. Can you attach a debugger and put a breakpoint in Display?

Feb 10, 2012 at 5:32 AM

You need a model, plain and simple. ICubePart needs to exist, otherwise you can't reference it.  But it doesn't need to have a record. You can just do public class ICubePart : ContentPart { ... }

Feb 10, 2012 at 6:45 AM

Hi Randompete & all who spent their time, THANKS! all is fine!

... plain and simple an 'empty' Model did it! like below:

PS: would it be beneficial to document this scenario somewhere to prevent an similar thread-ordeal'!?!? Or am I the only ignorant!
 but again, thanks a million, ed

using System.ComponentModel.DataAnnotations;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Records;
using System;

namespace ICube.Models {
  
    public class ICubePartRecord : ContentPartRecord {}
      
    public class ICubePart : ContentPart<ICubePartRecord> {}
              
}

Feb 10, 2012 at 6:52 AM

You shouldn't need the record; ICube part can just be a ContentPart, rather than a Contentpart<ICubePartRecord>.

But yes, more documentation can always help. I think the orchardproject.net docs go through the "standard case" which is basically ContentPart<TRecord>, but not the simpler case you have here.

Feb 10, 2012 at 7:27 AM

well, without the'public class  ICubePartRecord' I got also an error: are you missing  etc.
... for now I'm experimenting a bit to learn!

Because: I found already some different behaviour on this widget compared to the downloaded Bing.Map widget ... but this would be a seperate thread after
I'm more familiar! thanks ed
 

Feb 10, 2012 at 7:35 AM

Umm yeah that's why I said remove the reference to ICubePartRecord. Basically if you reference a class it has to exist, otherwise you get compiler errors. But ContentPart doesn't need a <TRecord>.

Feb 10, 2012 at 3:56 PM

ok, I'll appreciate your hint and will apply it the next time

thanks again for everything, ed