Hugoware

The product of a web developer with a little too much caffeine

Posts Tagged ‘Html

Render Partial — But With Arguments!

with 6 comments

One thing that I haven’t really liked about MVC was using RenderPartial instead of an actual UserControl. Its not that you can’t use them but that there is a disconnect between the control state and the render phase which makes it pretty much impossible to really work with them inline.

I say ‘pretty much’ because I’ve done a lot of work to let people use WebControls inline with MVC code.

Using the existing RenderPartial requires that you pass in the name of the UserControl that you want to render. You can also provide an object argument that is passed in as the ‘Model’ for the partial view. The UserControl can access the passed in object via the ‘Model’ property — even cast it into the correct type directly.

Personally, I use a lot of Models in my projects now. I used to suggest that you pass around objects using a wrapper for anonymous types but I’ve found that if you plan to move it from a Controller to a View or from a View to a UserControl then you ought to define a class.

Using RenderPartial Without Really Using It

So instead of calling RenderPartial directly, what about using the Model that we have in place to make the call for us. Not only that, we can even define our class to accept arguments directly. Here is an example of a simple dialog box…

using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MvcTest.Models {

    //simple dialog box example
    public class DialogBox {

        //rendering the dialog box
        public static void Render(ViewPage insideView, string title, string message) {
            insideView.Html.RenderPartial(
                "DialogBox",
                new DialogBox() {
                    Title = title,
                    Message = message
                });
        }

        //Properties
        public string Title { get; set; }
        public string Message { get; set; }

    }

}

Then we could simply use our code inline by calling the DialogBox.Render instead of the RenderPartial method.

<% DialogBox.Render(this, "My Title", "This is the message to display."); %>

You could also use an approach like this to make creating UserControl templates easier.

using System;
using System.Web.Mvc;
using System.Web.Mvc.Html;

namespace MvcTest.Models {

    //simple product list example
    public class ProductListing {

        //rendering the list of controls
        public static void Render(ViewPage insideView, List<Product>, Action<Product> renderRow) {
            insideView.Html.RenderPartial(
                "ProductListing",
                new DialogBox() {
                    AllProducts = products,
                    RenderRow = renderRow
                });
        }

        //Properties
        public List<Product> AllProducts { get; set; }
        public Action<Product> RenderRow { get; set; }

    }

}

And then you could call your method inline and provide the template action.

[View.aspx]

<!-- snip -->
<% DialogBox.Render(
         this,
         products,
         (item) => { %><li><% =item.Name %></li><% }
         ); %>
<!-- snip -->

[UserControl.ascx]

<%@ Control Language="C#"
    Inherits="System.Web.Mvc.ViewUserControl<MvcTest.Models.ProductListing>" %>

<h3>Featured Products</h3>
<ul>
<%
    foreach (Product item in this.Model.AllProducts) {
        this.Model.RenderRow(item);
    }
%>
</ul>

The above example is probably over simplified but you probably get the idea. This may not be a big gain, but if you plan to use the same UserControl often, then this might help simplify the call.

Written by webdev_hb

October 26, 2009 at 11:38 pm

Outlook Web Access via iPhone

with 2 comments

You may have seen my post a little while back about how I was starting to do some iPhone development for my job. For the most part the app is nothing more than a nice pretty front end to a handful of Web Services (hint: last blog post was along the same lines)

In any case, I’d rather my first attempt at iPhone development be a throw away project since I’m going to probably going to have to start over several times.

Learning Through Development

Whenever I offer up advice to a new programmer on what is the best way to learn programming I always say – “write a program that does something you want — you’ll learn a lot along the way and have motivation to finish it.”. Learning Objective-C was no exception for me.

Even though we use Exchange for our e-mail server at work, we don’t have the “Active Sync” enabled so you can’t link up with the iPhone through the built in e-mail application. So, instead, I decided to go a different route — use the existing Outlook Web Access and parse the HTML.


Picture 1

So with a couple of nice Regular Expressions and some HTTP calls we have a nice clean display of all the e-mails in my mailbox. Yep, that’s right — screen scraping via HTML… a little cheesy, but not bad since it works even if Exchange isn’t configured to allow it!

This was a perfect example of writing an application that met my need and allowed me to learn a new language at the same time… of course I’m not suggesting that I’m an Objective C expert or anything but at least now I can ditch my BlackBerry! :)

Hey, Who Puked On My Screen… Oh Wait, That’s Objective C

I’m definitely a spoiled programmer. Using .NET and C#/VB has definitely shielded me from some ugly languages out there. Objective-C is the kind of stuff that makes babies cry.

Developing iPhone is WAY different that anything that you have ever done in .NET. You’re adding all sorts of weird things like IBOutlet and IBAction so you can link them around all over the place — it is definitely a new experience. I’m going to have to write a ‘C# Developers Guide To iPhone Development’ to maybe save some other poor guy a lot of grief.

Still a .NET Guy

Getting into new languages and technologies on different platforms is always a good idea. You gain added perspective while increasing your skill sets (not to mention you look better on paper for your next job). Even if you don’t want to buy a Mac and play with the iPhone you can always tinker with a myriad of other languages on any number of free operating systems — Go do it!!

Don’t think that I’m converting – If anything using a Mac this much has solidified why I’m still die-hard Windows/ASP.NET/PC…

…But then again… MonoDevelop for Mac is looking kinda slick…

Written by webdev_hb

October 1, 2009 at 7:54 pm

WebForms : FrontPage For Programmers

with 9 comments

Yeah – I said it. I called WebForms FrontPage for programmers – whadaya goin’ to do?

Now before people start throwing hate mail at me its worth pointing out that up until MVC I used WebForms for all of my web development. In fact, I really do like WebForms. I think that they are especially great for whipping out quick internal projects that normally draw away from the time you could use developing something useful.

But, as much as I like WebForms, I think that too often they spew out more crap than value. If FrontPage was the way for a non-technical person to make a website then WebForms is the way for a non-web developer to make a website.

A Simple Example

(It’s worth noting my measurements are based on uncompressed HTML – I’m mostly pointing out the differences between output created by the developers – not the content that is compressed down the wire.)

Well here is a page that really rubs me wrong…

windows-example-1

[Microsoft.com/Windows]

Why? Nothing bad about it – the page looks pretty good… until you look under the hood at the source code. Once you start digging into it you find that the page is a whopping 123K and of that 28K is in the ViewState — clearly something that could have been done away with. You can also tell that ASP.NET gave a bunch of the elements on the page a unique ID even though they aren’t going to be referenced by any sort of Javascript. How about the id ctl00_BaseBody_FadingHeroEmbeddedSliverlight1_FadingHeroEmbeddedSL_ HeroBottomTitleShortDescriptionDivID (I had to put a break in the middle).

ASP.NET really does an incredible job abstracting the web so that a desktop programmer can jump right into web development, sometimes even using drag-and-drop controls *shudder*. It seems to me that web development ought to be done by people that understands the model.

Here is an example where you can tell that web developers had constructed it. It pains me to show it but I think it is relevant here since they are direct competition.

apple-example-1

[Apple.com/Mac]

Yeah, it’s the website of the enemy. But if you go over the page there is roughly the same amount of information (if not more) but their page is only 25K (smaller than the ViewState alone on the previous example). Even if you compare all of the resources on the two pages, the Apple site loads about 30K less in stylesheets and scripts than the Microsoft site. It is worth mentioning that the Apple site does load more images but their entire pages is full of large, high quality images — which is something that grabs attention much better than text. Not only that, but the Apple site actually does stuff!

Why? If you look at the source code you can an immediate difference between the two. The source code on the Apple page is cleaner, better designed and smaller. There is no ViewState or unnecessary ids for elements on the page. Everything (appears) to have been placed onto the page through careful consideration and not generated by some Page Lifecycle that injects code and markup into your page without you even knowing it.

So What Is My Point

Both these examples are two high profile sites. They are from two very competent technology companies — however, one looks a little less skilled to the other – at least from a web development perspective. It seems to me that extra time and effort should have been placed by the Microsoft developers to trim out all the fat and make it as web friendly as possible.

I might be nit-picking at the HTML output but I do think its relevant. That code – even if it is compressed – is the final rendered output from a WebForms page. As soon as the page opens there is immediately markup errors, unmatched tags, extra body elements. It’s clearly not the best it can be. I’m not trying to make Microsoft look bad either – personally, I want to work for them some day, but the point is that in order to improve then you must first be honest with yourself and those around you.

WebForms are a powerful tool – don’t get me wrong – but it seems to me that they have abstracted web development too far. I always thought it was really cool about .NET the way you could go from web, desktop, console, mobile or whatever development you wanted to and it was still like second nature! It allowed you to focus on solving problems and less on how each area was supposed to work.

I’m not saying people can’t develop great applications with WebForms. In fact I still use them from time to time when I need to hack out a quick application that only the internal eyes of my company are going to see. However, when I’m browsing the web and come across a website that is packing a 50K ViewState or is littered with wasteful, pointless 40 character long ids, I just can’t help but feel that WebForms is starting to hurt the web a little.

That’s why I recommend that if you haven’t already, go try out ASP.NET MVC. It doesn’t take long to break away from WebForms and you’ll probably feel more comfortable within a few days.

Written by webdev_hb

August 28, 2009 at 2:12 am

New Hugoware.net Site

with 10 comments

For the longest time now Hugoware.net has basically been the home for jLinq. Lately, I’ve been working on a new version of my site — one that represents all of the stuff I do and not just one of my projects. After working on the site for about a week I’ve updated with a brand new look and grouped all of my projects together into one site.

I’d love to get some feedback — so use the ‘Contact Me’ section to tell me if you think something could be improved.


hugoware

And of course, there is my Twitter Bird (he’s open source as well :) )

twit

There isn’t much to talk about with the new site. Basically it is an ASP.NET MVC site with personal information and projects on it.

However, I’m always interested in hearing feedback. If you think something about the site is missing or could be improved, please let me know!

Written by webdev_hb

August 14, 2009 at 2:53 am

Using WebControls In ASP.NET MVC Views – Part 3

with 16 comments

WebControls In MVC Series

I mean’t to have this post out this morning, but I was busy working on getting my personal website online — Please check it out and tell me what you think!

Up until now all of the post in this series have been tests to see if we could make the process work. Now, finally, now we get into some real code that we can actually use. I’ll take just a little bit of space to explain how it works and how to set it up, but then the rest of the post to explain how to use it.

Getting The Code Setup

Before we discuss how to use the code lets go over briefly how to setup the code.

To start, the code you need to download is found at the end of the post. When you download it, put both the .cs and the .aspx file into your project. By default the code expects the .aspx to be in your Views directory, but you can move it — but if you do then you need to update MVCWebFormExtensionMethods._WebFormRenderControl.TEMPLATE_PAGE with the new location (yeah, it’s a long name :) ).

Optionally, you can make a couple changes to your Web.config to make sure that the extension method and MvcControlGroup are available to the rest of your application without needing to add anything special onto each of your pages.

<configuration>
    <!-- snip... -->
    <system.web>
        <pages>
            <controls>
                <!-- snip... -->
                <add tagPrefix="mvc"
					namespace="MvcWebControls"
					assembly="YourProjectAssemblyName" />
            </controls>
            <namespaces>
                <!-- snip... -->
                <add namespace="MvcWebControls"/>
            </namespaces>
        </pages>
    </system.web>
    <!-- snip... -->
</configuration>

I’ve hidden most of the Web.config from this example, so make sure to add the areas you see above, not simply replace your entire config.

The rest of this post goes over some demos found out on my website, you may want to follow along to better understand what is going on.

Example 1 — Simple Postbacks

<html>
    <head runat="server">
        <title>Simple Postback Example</title>
    </head>
    <body>
        <h2>Just A Simple Form</h2>
        <% this.Html.WebForm((form) => { %>
            <% form.RenderControl(new TextBox()); %>
            <% form.RenderControl(new Button() { Text = "Save" }); %>
            <hr />
            <% form.RenderControl(new Calendar()); %>
        <% }); %>
    </body>
</html>

For the first example, we want to see if we can use a few simple WebControls and see if our values are posted back the way we would expect. In this example we add a TextBox, Button and Calendar. Pay attention to how this HtmlHelper method works.

If you notice, the method excepts a delegate to render the control onto the page. We do it like this because it allows us to provide markup to our page along side with the WebControls. The method accepts a single parameter the MvcWebForm. Think of this as a very, very simple version of a WebForm.

The MvcWebForm gives you access to the page that is being used to render the controls. This is important to remember and I’ll go over it in the next section.

Example 2 — Using Events

This is handy so far but unless we are using some events for our controls, nothing much has changed. Let’s look at another example.

<html>
    <head runat="server">
        <title>Using Events</title>
    </head>
    <body>
        <h2>Simple Button Click Event</h2>
        <% this.Html.WebForm((form) => { %>
            <strong>Clicked : </strong>
            <% Label text = form.RenderControl(new Label() { Text = "0" }); %>

            <br /><br />
            <% Button submit = form.RenderControl(new Button() { Text = "Add" });
               submit.Click += (s, e) => {
                   int value = 0;
                   int.TryParse(text.Text, out value);
                   text.Text = (++value).ToString();

                   //post back this information
                   form.Page.ClientScript.RegisterStartupScript(
                       typeof(Page),
                       "confirm",
                       string.Format("alert('Updated to {0}');", text.Text),
                       true
                       );
               }; %>
        <% }); %>
    </body>
</html>

In this example we are assigning a Click event to the button we added to the page. You’ll notice when we run this example the value is incremented up by one on each press.

Notice that we use form.Page instead of this.Page. When you use this code you must remember that you are working with two separate Page instances. One for the View and the other for rendering the control. In this example we use RegisterStartupScript to display an alert box. If you were to have used this.Page.ClientScript, nothing would happen.

It’s a subtle difference that you are going to want to keep in mind while you use this class.

Example 3 — MvcControlGroup

So far all of our examples have only used a couple controls that were all rendered inline with the rest of the page. While this is going to work in most situations, some places won’t work as well.

The example below shows how you can use the MvcControlGroup to group controls together, for example, the Wizard control.

<html>
    <head runat="server">
        <title>Using Events</title>
    </head>
    <body>
        <h2>Using Wizard Control with MvcControlGroup</h2>
        <div>
        <% this.Html.WebForm((form) => { %>
        <mvc:MvcControlGroup runat="server" >
        <asp:Wizard runat="server" >
            <WizardSteps>
                <asp:WizardStep runat="server" Title="Personal Information" >
                    <p>Leaving fields blank will catch the validators.</p>
                    <strong>Name</strong>
                    <asp:TextBox ID="name" runat="server" />
                    <asp:RequiredFieldValidator runat="server"
                        ControlToValidate="name" ErrorMessage="Must provide a name" />
                    <br /><br />

                    <strong>City</strong>
                    <asp:TextBox ID="city" runat="server" />
                    <asp:RequiredFieldValidator runat="server"
                        ControlToValidate="city" ErrorMessage="Must provide a city" />
                </asp:WizardStep>

                <asp:WizardStep runat="server" Title="Reservation Date" >
                    <strong>Date Requested</strong>
                    <asp:Calendar ID="date" runat="server" />                 

                </asp:WizardStep>

                <asp:WizardStep runat="server" Title="Confirm" >

                    <h2>Confirm This Order?</h2>
                    <p>This step maps to a Controller Action before submitting</p>

                    <% MvcWebForm.Current.Action = "/Projects/MvcWebForms/Submit"; %>
                    <% MvcWebForm.Map(() => new {
                        name = name.Text,
                        city = city.Text,
                        date = date.SelectedDate.ToShortDateString()
                       }); %>

                </asp:WizardStep>
            </WizardSteps>
        </asp:Wizard>
        </mvc:MvcControlGroup>
        <% }); %>
        </div>

    </body>
</html>

Just like with other controls, the MvcControlGroup must be rendered in a separate page instance. This control moves it to the correct context before it is processed.

If you remember, the idea behind this project was to allow people to use WebControls with Mvc — not just use WebControls in Mvc. On the last step we point our form to a Controller Action and use a method called Map to format our information for the postback.

When the user finished the Wizard they can post the finished form back to the correct Controller Action!

**whew** — that’s a lot to take in!

Limitations

There are a couple limitations that still need to be worked through…

  • HTML output must be well formed – If your control outputs bad HTML, this thing will croak. The reason is that instead of using Regular Expressions to try and match content the output is parsed using the XDocument.
  • PageMethods, AJAX calls will probably not work – Controls like the UpdatePanel or using PageMethods will most likely not work anymore. Some additional work is going to be required to make those work.

I’m sure there is more that needs to be looked at but at this point it seems as if it can be used — at least for testing.

Please let me know if you have any ideas, feedback or suggestions! I’m going to continue to work on this and see what kinds of improvements can be made.

Source Code

Download MvcWebForms.zip

.

Written by webdev_hb

August 12, 2009 at 8:58 pm

More jQuery Magic – iPhone Style Password Box

without comments

I like to think of myself as a technology-neutral developer that can look past any Microsoft-Apple rivalries and instead focus on the best tool for the job…

I like to think that — but I know that I’m a total Microsoft fanboy… :)

So wouldn’t you know it that my entire FAMILY has been purchasing Apple stuff lately? Each (adult) family member has an iFail iPhone (except me, of course), my brother has an iTouch, sister-in-law with MacBook – Blasphemy! From my own flesh and blood!! ACK!!

However, despite this treachery I did discover that I did like the way that Apple handled inputting passwords.

iPhone Style Password Box

It’s worth mentioning up front that this code is just an experiment — it’s not a finished product and probably shouldn’t be pasted into a live site.

If you’ve used an iPhone before then you’ve probably noticed that you can see the last character you entered when inputting your password. This character disappears after a moment or two or the next time you enter a character. Using some jQuery and a hidden password field I attempted to create something similar.

[Sample version here.]

password-style-1

Now unfortunately, by using a div instead of an input I’ve taken away the ability to select the characters in the field. When I was working on this I had an idea that I might try using the ‘contenteditable’ property instead and then display the normal password box for browsers that don’t support it.

Why Not A Input[Type=Text]

I tried doing a similar idea with by using a regular text box and just masking the characters on the fly, but ran into a problem where pasting a password would cause the whole thing visible for a moment — which seems like too much of a risk.

Another Approach

The basic idea of the Apple style password box was to show the most recently entered character but the first example lost some of the usability of a normal password box. I figured I’d give the idea a second pass, but adjusted it to be a little more HTML friendly.

[Sample version here.]

password-style-2

You’ll notice in this version that the characters actually float up as you enter them. Similar to before, after a few moments, or when you press a new key, they will disappear.

This version is better from a usability standpoint, but it does have a couple problems of its own. For example, if you enter a really long password then the floating box stops moving at the end — no big deal right? Well for the end of the box, no, it looks fine — but if you click back out in the middle then your floating hints may be off-centered.

Simple But Effective Interface Designs

The code above isn’t ready for publishing, but they are some interesting examples of how you can take a typical form element and use a little jQuery to make some great usability enchancements to them.

You may have read some of my earlier jQuery posts about mimicking Vista style password boxes or creating search highlighting for web pages and noticed that it doesn’t take that much code to transform the functionality of your pages.

How do you enhance your pages for your visitors? It doesn’t take much!

Written by webdev_hb

July 22, 2009 at 6:24 am

iTextSharp – Simplify Your HTML to PDF Creation

with 104 comments

Update: A second version that works in .NET 2.0 has been included at the end of this post.

If you’ve ever had to generate PDFs on the fly then you may have run into iTextSharp, which is a port of iText for C#. It isn’t as straight forward as some people might like, but it is certainly a powerful tool once you figure it out.

Normally, if you wanted to take some HTML and turn it into a PDF you would write a lot of extra code to recreate the document in PDF format, but lucky for all of us, iTextSharp also supports HTML. Again, it isn’t exactly straight forward, but to help I wrote a quick wrapper today to help with the process.

HtmlToPdfBuilder allows you to build a PDF using HTML and hides the complexities of working with iTextSharp. You still need iTextSharp to get this project to run, so make sure to include it.

To start, create a new HtmlToPdfBuilder object. As part of the constructor you’ll need to set the document size. It’s actually a Rectangle, but iTextSharp has predefined sizes already available in the PageSize class (constants)

//Page sizes are found in iTextSharp.text.PageSize
HtmlToPdfBuilder builder = new HtmlToPdfBuilder(PageSize.LETTER);

After you have the builder you can add as many pages as you would like using the .AddPage() method. You can also access each of the pages by their index on the builder you create.

HtmlPdfPage first = builder.AddPage();
//also found at builder[0]

HtmlPdfPage second = builder.AddPage();

Once you’ve added your pages you can start adding your HTML with .AppendHtml().

first.AppendHtml("<h1>Hello World</h1>");

//you can also use params for formatting
second.AppendHtml("<h1>{0}</h1><span>{0}</span>", "Hello Second Page", "Another Param");

Next, you’re going to want to apply some styles to your PDF document, you can use a couple methods. First, the .AddStyle() let’s you add a single style to your page. The first parameter is the selector, such as "H1" or ".totals", the second parameter is a single line of CSS such as "color:#F00;font-weight:bold;".

There is also a method called .ImportStylesheet() that accepts an absolute path (not relative) to a stylesheet and adds all of the styles it finds. I was pretty pleased with the method because I was able to do the entire thing with a single Regular Expression.

//add individual styles
builder.AddStyle("H1", "color:#F00");
builder.AddStyle("p", "font-weight:bold;text-decoration:underline;");

//import an entire sheet
builder.ImportStylesheet("c:\\stylesheets\\pdf.css");

It’s worth mentioning that all of my efforts to set heights, widths, paddings and margins didn’t go so well. I’m not sure what the rules are when it comes to that part so be warned.

Finally, you’re ready to save your document. Use the .RenderPdf() method to get the bytes of your PDF.

byte[] file = builder.RenderPdf();
File.WriteAllBytes("c:\\output\\final.pdf", file);

If you’ve worked with iTextSharp before, or you want a little more control over the rendering process, the builder has two events named BeforeRender and AfterRender that give you access to the iTextSharp classes PdfWriter and Document.

Hopefully, this helps simplify working with HTML and PDFs with iTextSharp. Share your thoughts or suggestions!

Source Code

Download HtmlToPdfBuilder.cs

.

Below is a test version for .NET 2.0 – Please let me know if you discover any bugs. Since I am using Visual Studio 2008 I’m not always aware when there is code that won’t work in previous versions.

Download HtmlToPdfBuilder.cs (for .NET 2.0)

Don’t forget, you still need to download iTextSharp and add it as a reference in your project.

Written by webdev_hb

May 8, 2009 at 3:04 am