Creating Custom Widget in Visual Studio in Orchard 1.7

Topics: Core, Writing modules
Aug 8, 2013 at 5:05 AM
Edited Aug 8, 2013 at 5:08 AM
Hello, I am a newbie to Orchard framework!
I am trying to build a very simple widget with two input fields Name and Email address.

I am following this post from Tony Johnson: http://www.deepcode.co.uk/search?q=how+to+build+a+widget+without+a+model+in+Orchard.

Migration.cs:

public int UpdateFrom22()
    {
        ContentDefinitionManager.AlterTypeDefinition("QuickLinkWidget", builder => builder
                .WithPart("QuickLinkWidgetPart")
                .WithPart("CommonPart")
                .WithPart("WidgetPart")
                .WithSetting("Stereotype", "Widget"));

        return 23;
    }

ContentPartRecord

public class QuickLinkWidgetRecord : ContentPartRecord
{
    //We shall not define any property for this class.
    //We shall not create any HANDLER for this widget because we do not need to store any data to our database.
}

ContentPart

public class QuickLinkWidgetPart : ContentPart<QuickLinkWidgetRecord>
{
    //Again we shall not definte any Record property here......
    //We shall not create any HANDLER for this widget because we do not need to store any data to our database.
}

Handler

Did not define any as I don't have deal with any repository.

Driver

I do not need any Editor template defined, so only Display is what I kept.

public class QuickLinkWidgetDriver : ContentPartDriver<QuickLinkWidgetPart>
{
    protected override DriverResult Display(QuickLinkWidgetPart part, string displayType, dynamic shapeHelper)
    {
        //We do not have any property defined in Model class.
        //So we don't have to assign any Default values to anything!
        //We shall just retusn a SHAPE of the widget

        return ContentShape("Widgets_QuickLinkWidget", () => shapeHelper.Widgets_QuickLinkWidget());
    }
}

Placement.info

<Place Widgets_QuickLinkWidget="AsideFirst:1" />

And finally the View: Views/Widgets/QuickLinkWidget.cshtml

@using Emfluence.Intrust.Models;
@model Contact
<h2>Our Side link widget</h2> Nothing extra I added here, just want to see it rendering first!


Please help me understanding what I am doing wrong. Why I am not able to see the widget rendered at all? I am stuck with it for the last 3 days :(
Developer
Aug 8, 2013 at 6:39 AM
I don't know if this is related, but since you're not storing custom part properties into a database table, you don't need to derive your content part class from ContentPart<TRecord>. Instead, simply derive it from ContentPart:
QuickLinkWidgetPart : ContentPart
Check your log files in App_Data/Logs to see if there's anything suspicious there.
Alternatively attach the debugger (set Exceptions to Thrown to break on thrown exceptions even though they are handled, this may give you some clues).
Aug 8, 2013 at 8:06 AM
Edited Aug 8, 2013 at 8:07 AM
Doesn't the problem is the View being not directly under View folder.
Orchard does not accept sub folders as Views/Windget/xxx.cshtml (only for pure MVC views)
Try moving it to View/QuickLinkWidget.cshtml
Aug 8, 2013 at 9:57 AM
But then how my other Content Parts are getting rendered? Does Orchard take different approaches for rendering a ContentPart and a Widget?
Aug 8, 2013 at 10:03 AM
Edited Aug 8, 2013 at 10:04 AM
No luck! Do I have to make any change in Layout.chtml or somewhere else. I am building this widget inside a custom module. In fact this widget does not require any model. How do I achieve that?
Aug 8, 2013 at 10:08 AM
I don't understand your question ? Your widget rely on a part so it is finally rendered as a part with the shape defined it the driver display method.
But you have to go on the Widget Admin Menu and add your widget to the layer(s) where you want it: see documentation.
Aug 8, 2013 at 10:18 AM
Edited Aug 8, 2013 at 10:19 AM
CSADNT wrote:
I don't understand your question ? Your widget rely on a part so it is finally rendered as a part with the shape defined it the driver display method.
But you have to go on the Widget Admin Menu and add your widget to the layer(s) where you want it: see documentation.
Yes, I have done that already, But the view content is not rendering. This is the problem. Please see the screenshot at http://screencast.com/t/0hX0NCmzNGA. The content is supposed to come under the title "Intrust Bank Quick Navigation"

And here is how I set up the widget http://screencast.com/t/HwrGHwkBnf
Aug 8, 2013 at 10:27 AM
Try to change your placement for

<Place QuickLinkWidget="Content:0" />
Aug 8, 2013 at 10:33 AM
Edited Aug 8, 2013 at 10:35 AM
CSADNT wrote:
Try to change your placement for

<Place QuickLinkWidget="Content:0" />
It disappears from AsideFirst, which is understandable. But not rendered in Content area. Please see this http://screencast.com/t/50ZRckj8qhL
Here is the project tree (View is in the root of Views folder as you suggested) and the Content of the view.

http://screencast.com/t/IEKFZETd

Edit:
here is the Placement.info file content

<Place Parts_Contact="Content:7"/>
<Place Parts_Contact_Edit="Content:5"/>
<Place Parts_Question="Content:7"/>
<Place Parts_Question_Summary="Content:5" />
<Place Parts_Question_Edit="Content:5"/>
<Place Parts_Expert="Content:7"/>
<Place Parts_Expert_Edit="Content:5"/>
<!--<Place QuickLinkWidget="AsideFirst:1" />--> This line is commented out
<Place QuickLinkWidget="Content:0" />
Aug 8, 2013 at 10:41 AM
not sure the commented out works in .info files.
When I set the placement for a widget I always use content and it works.
Aug 8, 2013 at 10:53 AM
CSADNT wrote:
not sure the commented out works in .info files.
When I set the placement for a widget I always use content and it works.
Superb!! I removed the comment from Placement. Removed the Model reference from the View and here is the result.
http://screencast.com/t/v0Au5yVSDjA

Thanks a ton!! You saved my life. :)
Aug 8, 2013 at 10:58 AM
You're welcome :), looks nice.
In fact even in different zones than the central content, you may use header/content/footer :xx for positioning.
Aug 8, 2013 at 11:02 AM
CSADNT wrote:
You're welcome :), looks nice.
In fact even in different zones than the central content, you may use header/content/footer :xx for positioning.
Wow. I did not not have any idea of it!
I must say this community forum is lightning fast. I never seen such quick replies in ANY community before this!
I have started liking Orchard once again :)
Aug 8, 2013 at 1:46 PM
Sorry to disturb again! This time I have created a new widget which is for Newsletter signup.
I did exactly the same - Created Content part, Content part record, written Migration and a View which is again placed under Views root.

The problem is the same - not displaying the content! I have added the Widget to AsideFirst from admin and the position has been set to 2 while the other has 1.

The extra thing I have done is created a Controller:

public class NewsletterSignupWidgetController : Controller
{
    public ActionResult NewsletterSignup(FormCollection formCollection)
    {
        var newsletterUserName = formCollection["txtNewsletterUserName"];
        var newsletterEmail = formCollection["txtNewsletterUserEmail"];

        return Redirect("/thank-you");
    }
}
ContentPart: Models\NewsletterSignupWidgetPart
ContentPartRecord: Models\NewsletterSignupWidgetRecord
View: Views\NewsletterSignupWidget.cshtml
Controller: Controllers\NewsletterSignupWidgetController.cs
Placement info: <Place NewsletterSignupWidget="Content:1" />

Content of the View:

<h3>E-newsletter Sign-up</h3> @using (Html.BeginForm("NewsletterSignup", "NewsletterSignupWidgetController", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="row-fluid">
    <div class="span6">
        <label>Name</label>
        <input type="text" name="txtNewsletterUserName" required maxlength="50" style="width: 95%" />
        <label>Email</label>
        <input name="txtNewsletterUserEmail" type="email" required maxlength="85" style="width: 95%" /><br />
        <center>
            <button class="btn pull-right">Submit</button>
        </center>
    </div>
</div>
}

@using (Html.BeginForm("NewsletterSignup", "NewsletterSignupWidgetController", FormMethod.Post)) where "NewsletterSignup" is the Controller action and "NewsletterSignupWidgetController" is the Controller class name.

Nothing different I did except the Controller. I know its a silly thing to get back to you with the similar problem, but please forgive my considering my exposure to Orchard!
Aug 8, 2013 at 2:24 PM
If exactly same process it should work.
Check the log file in App_Data\logs.
Aug 8, 2013 at 6:47 PM
I checked Log file but has nothing in it. 0 Kb!
Aug 8, 2013 at 7:15 PM
May be your cshtml contains error, try with simpler one.
If you use VS put break points inside and in your part. Good luck.
Aug 8, 2013 at 7:38 PM
Fixed! Case error in class name Migration.cs. Sorry for bugging you.
Aug 8, 2013 at 7:44 PM
No pb.