Posts Tagged ‘Programming’
Meanwhile, Back At CodePlex…
Just a quick update — I’ve been working on Flow Based MVC Controllers some more and hope to do a blog post about them in the next couple days…
For now, I’ve moved some of my other MVC projects onto CodePlex so there is a better home for them (than my own website of course
)
Mvc Content Marker
A few months ago I wrote some code that allowed you to write to different parts of the page using inline code — You probably know it isn’t easy to add a stylesheet or script to a different part of the page since after render code has finished you can’t go back and write over it.
This code makes it so you can place a marker on the page and then write back to it no matter where you are at. It also supports forward looking markers (meaning markers that haven’t been added to the page yet) so it makes it easy to add scripts to the footer of your page from higher up in the document.
As it turns out Spark has something similar to this — but if you aren’t ready to jump into Spark then this still might be handy for you. (Spark is cool, don’t get me wrong though)
Mvc WebForm
Mvc WebForm does exactly what you think it does — It lets you place a WebForm inline with your Mvc code. I isn’t perfect at all and in all honestly was just to see if it was possible. As it turns out you can have basic event handling, button clicks, data grids — whatever — and it works directly in your Mvc Views. Neat stuff even if it is evil.
I expected to be shunned by the development community with this but surprisingly I got several ‘thank you’s and ‘good job’s — Funny how that works out sometimes.
Flow Based MVC Controllers
I’ve been working on a project lately that has required that a controller follows a series of logical steps before it reaches the end. I don’t want users to access the last step until earlier steps have finished. The process also branches into separate paths depending on their selections.
One of the things that bugged me is I hated having so much logic devoted to checking to see if steps had been done before I continued. For example, checking if an image had been uploaded OR if they selected one from a gallery. Most likely I could simply create a property that checked for the state of things, but I wanted to come up with a reusable way to manage the flow of a controller.
The Flow
So here is an example of what kind of flow would go through this. This controller allowed a customer to provide a custom image or choose one from a gallery. The requirements at the end change depending on what a user selects.
Right now I’ve only developed some rough code — but here is a basic idea of how the flow can be controlled automatically.
The Basics
This first example shows the basic idea behind identifying a method as requiring a step to complete. An attribute can be applied to
//for now, the flow process uses extension methods instead of an inherited class
using MvcFlow.FlowExtensionMethods;
//A controller for MVC
public class ShopController : Controller {
//required override to check steps automatically
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
//extension method to check an action in the flow
this.ProcessStep(filterContext);
}
//this step has no requirements so it can be browsed to at any time
public ActionResult Index() {
returns this.View();
}
//this has no requirements but it does APPLY a step if the validation is successful
public ActionResult ValidateUser(string username, string password) {
if (this.PasswordIsCorrect(username, password)) {
//an extension method to update the steps for the flow
this.ApplyStep(Steps.UserValidated);
return this.RedirectToAction("SelectType");
}
//if the process doesn't apply the next allowed step then it can't proceed
else {
return this.RedirectToAction("Index");
}
}
//this step cannot be executed until Steps.UserValidated has been applied
//which is done in the successful validation step
[StepRequires(Steps.UserValidated)]
public ActionResult SelectType() {
return this.View();
}
//snip...
The important thing to notice is that there are only three things required to make this process work.
- Override the OnActionExecuting method to perform the validation. By overriding this step we can make sure an action is allowed to be executed — and if not, redirect the user.
- Add an attribute to describe step requirements. The attribute
StepRequiresallowed us to define what steps must have been completed before they can execute this action. - Apply steps after successful validations. If requirements have been met then the step can be saved and a new set of actions will open up.
Removing And Branching
Here is another example of the code that shows how flow can be managed…
//snip...
//this step requires validation has happened -- but it also removes if
//they have selected certain future steps. This means if someone browses back
//to the page then they are required to answer the question again
[StepRequires(Step.ValidatedUser)]
[StepRemoves(Step.SelectCustom | Step.SelectGallery)]
public ActionResult ChooseType() {
return this.View();
}
// BRANCH 1
// Custom --------------------------
//Applies the SelectCustom option -- but also removes the option for
//the other branch (if it was even found)
[StepRequires(Step.ValidatedUser)]
[StepRemoves(Step.SelectGallery)]
public ActionResult SelectCustom() {
this.ApplyStep(Step.SelectCustom);
return this.RedirectToAction("UploadImage");
}
//This step requires that both the validation and select custom steps have been applied
[StepRequires(Step.ValidateUser | Step.SelectCustom)]
public ActionResult UploadImage() {
return this.View();
}
// BRANCH 2
// Gallery --------------------------
//Applies the SelectGallery option -- but also removes the option for
//the other branch (if it was even found)
[StepRequires(Step.ValidatedUser)]
[StepRemoves(Step.SelectCustom)]
public ActionResult SelectGallery() {
this.ApplyStep(Step.SelectGallery);
return this.RedirectToAction("ShowGallery");
}
//This step requires that both the validation and select gallery steps have been applied
[StepRequires(Step.ValidateUser | Step.SelectGallery)]
public ActionResult ShowGallery() {
return this.View();
}
Unfortunately, the attributes are a bit difficult to read but the general idea is to break the flow of the controller into two parts — each existing separate from each other but within the same controller.
You’ll notice in these steps we can use our enumerated type to create more than one requirement for an action (for example Step.ValidatedUser | Step.SelectCustom ). We can also use the RemovesStep attribute to automatically move back the current point of the flow.
Too Confusing?
I wrote a lot of the code to do this process today but I’m looking for some thoughts about this process. Is this too much work? Too confusing? Not really helpful?
Do you spend enough time managing flow in your applications that a framework like this could help?
Vacation Week!
I’ve been on vacation this week and didn’t spend much time programming… well, not on anything official at least. Mostly I’ve been poking around at stuff between games of Modern Warfare 2 and my chore list from The Wife. One of the more interesting things I’ve been playing with is using MySql with MonoDevelop and Ubuntu.
Since MSSQL normally costs extra in a hosted environment I typically end up using a handful of XML files or serialization to keep track of information. But now that I’ve been using Mono I started to consider that MySQL might be an option for further projects (especially since it’s normally free in hosted environments).
I did a post recently about getting started with cross platform development where I listed some resources to get you started but I didn’t mention anything about using SQL. Below are some tools that can get you started.
MySQL (Server)
Setup for the actual SQL server instance — Standard stuff here…
MySQL GUI Tools and the MySQL Workbench
Great set of tools to work with your SQL server instance. Just look at how polished some of these tools actually are!
A couple warnings before you get too far. Linux (or at least Ubuntu) is case sensitive — this means that if you try to include the DLL files for MySQL in your Mono project the case must match! When I downloaded the files they were all in lower case but the DLLs were imported using camel case (mysql.data.dll as opposed to MySql.Data.dll)
Also, I don’t see any way to use LINQtoSQL with MySQL (and it wouldn’t make sense if it did anyways). Be prepared to start writing your own queries just in case.
jLinq Update (2.2.1)
I’m off from work this week so the first thing I did was get some work done on jLinq. I’ve had a few bugs I’ve needed to sort out along with a new feature I wanted to implement. I’m also going to be working on documentation this week. Previously, I had created a Wiki and was hoping that people might add to the documentation… but instead spam bots pretty much ruined it so I’ll be starting over from scratch… oh well..
New Features
jLinq itself doesn’t really have a new feature but instead a new way to get the jLinq library. Instead of simply downloading a standard jLinq library you can use the new online jLinq Framework Generator to select only the functionality that you want to include. You can still download the basic pack but this option gives you a little more control what goes into your version of jLinq.
Changes
The most notable change for jLinq is that all of the operator commands have been included as standard functions for the framework. Before, these functions were actually methods extended onto the framework. Since these functions are required for jLinq to work I’ve moved them so that they are in every jLinq framework by default.
Bug Fixes
orderBy with joined records would return incorrect results
jLinq uses eval to figure out the values of field names since you can provide methods, array indexes or whatever. The code used to sort the values wasn’t getting the values correctly so the sorted result was always wrong.
using 0 in certain comparisons would return incorrect results
Ah, this one was fun. So check out the code below…
var values = [ 0 ];
var index = 0;
var a = !values[index];
var b = values[index] == null;
So what is a and what is b? If you said true and false then give yourself a cookie.
jLinq uses the number of arguments passed to help determine if anything is being memorized (like the field name). jLinq makes a quick pass to select all values until it finds a null value… or at least that is what I meant for it to do. Unfortunately, I wasn’t thinking when I wrote that method and didn’t check explicitly for null.
Feedback
If you find any problems with jLinq or have any suggestions, please leave a comment or contact me directly.
Code Performance Measuring With Enclosures
I’m sure that there are many libraries available to help measure the execution of time inside of an application but I spent some time the other day writing a quick class to help me time segments of code.
The idea was to use an Anonymous Method to wrap a section of code with a Stopwatch to check the total time of execution. Additionally, since methods could be Anonymous, you could nest the measurements to see how long specific sections would take.
Anyways, here is some source code to play around with.
/// <summary>
/// Simple measuring of sections of code
/// </summary>
public class CodeBlockTimer {
#region Private Fields
//holds the current time for this measurement
private Stopwatch _OverallTime;
//container for the measured code sections
private List<object> _Blocks = new List<object>();
//the nested level for the code block
private int _Level = 0;
#endregion
#region Methods
/// <summary>
/// Stops this code block timer
/// </summary>
public void Stop() {
this._OverallTime.Stop();
}
/// <summary>
/// Adds a block of code to measure
/// </summary>
public void Measure(Action block) {
this.Measure(block.Method.Name, block);
}
/// <summary>
/// Adds a block of code to measure with a defined name
/// </summary>
public void Measure(string identity, Action block) {
//start the overall timer if needed
if (this._OverallTime == null) {
this._OverallTime = Stopwatch.StartNew();
}
//check and make sure this timer wasn't already stopped
else if (!this._OverallTime.IsRunning) {
throw new InvalidOperationException(
"This CodeBlockTimer has already been stopped and cannot measure additional code blocks."
);
}
//create the container
_StartBlock start = new _StartBlock(identity, this._Level++);
_EndBlock end = new _EndBlock(start);
//run this section of code
this._Blocks.Add(start);
start.Timer = Stopwatch.StartNew();
block();
start.Timer.Stop();
this._Blocks.Add(end);
//and revert the level
this._Level--;
}
/// <summary>
/// Writes the results to the Console
/// </summary>
public void ToConsole() {
//make sure all of the jobs have finished
if (this._Level > 0) {
throw new InvalidOperationException(
"Cannot report the final summary until all code blocks have completed."
);
}
//stop the overall timer
if (this._OverallTime.IsRunning) {
this._OverallTime.Stop();
}
//showing code groups
Func<int, string> treeLine = (count) => {
string start = string.Empty;
for (var i = 0; i < count; i++) {
start = string.Concat(start, "| ");
}
return start;
};
//display each code block
foreach (object item in this._Blocks) {
//if this is a starting block, show the work has started
if (item is _StartBlock) {
_StartBlock block = item as _StartBlock;
Console.WriteLine(
"{0}[Begin] {1}: {2}",
treeLine(block.Level),
block.Identity,
block.Level
);
}
//if this is the closing block, display the timer result
else if (item is _EndBlock) {
_EndBlock block = item as _EndBlock;
Console.WriteLine(
"{0}[End] {1}: {2} ({3})",
treeLine(block.StartingBlock.Level),
block.StartingBlock.Identity,
block.StartingBlock.Level,
block.StartingBlock.ToTimeString()
);
}
}
//and display the summary
Console.WriteLine(
"\nTotal Blocks: {0}\nTotal Time: {1}",
this._Blocks.Where(item => item is _StartBlock).Count(),
CodeBlockTimer._ToTimeString(this._OverallTime.ElapsedMilliseconds)
);
}
#endregion
#region Static Methods
//creates a meaningful time string from some milliseconds
private static string _ToTimeString(long ms) {
if (ms > 60000) {
return string.Format("{0:0.0}min", (double)ms / 60000d);
}
else if (ms > 1000) {
return string.Format("{0:0.0}sec", (double)ms / 1000d);
}
else {
return string.Format("{0}ms", ms);
}
}
#endregion
#region Timing Classes
//the marker for the start of a code block
private class _StartBlock {
//starts a new block to check the starting time
public _StartBlock(string identity, int level) {
this.Identity = identity;
this.Level = level;
}
//the identifying name for this code block
public string Identity { get; private set; }
//the level this starts at
public int Level { get; private set; }
//the timer for this code block
public Stopwatch Timer { get; set; }
//provides a meaningful time value
public string ToTimeString() {
return CodeBlockTimer._ToTimeString(this.Timer.ElapsedMilliseconds);
}
}
//marker for the finishing of a code block
private class _EndBlock {
//starts a new block to check the ending time time
public _EndBlock(_StartBlock start) {
this.StartingBlock = start;
}
//the open block this code was started in
public _StartBlock StartingBlock { get; private set; }
}
#endregion
}
You can use the code inline with existing code to measure sections of the code. If you are using an existing method then the name will automatically appear in the final report. Otherwise you can use the default name or provide your own identity (which can help provide meaningful names for Anonymous Methods).
//create a monitor
CodeBlockTimer monitor = new CodeBlockTimer();
//start measuring a block
monitor.Measure("First Method", () => {
//simulate execution time
Thread.Sleep(300);
//measure a block without an identity
monitor.Measure(() => {
Thread.Sleep(500);
//measure a defined method
monitor.Measure(DoSomething);
});
//provide an identity for an anonymoure method
monitor.Measure("Quick Call", () => {
Thread.Sleep(250);
});
//more simulated execution time
Thread.Sleep(300);
});
//stop measuring the timer (or simply call ToConsole())
monitor.Stop();
//Display the results of the method to the console
monitor.ToConsole();
And the results…
[Begin] First Method: 0
| [Begin] <Main>b__1: 1
| | [Begin] DoSomething: 2
| | [End] DoSomething: 2 (1000ms)
| [End] <Main>b__1: 1 (1.5sec)
| [Begin] Quick Call: 1
| [End] Quick Call: 1 (250ms)
[End] First Method: 0 (2.4sec)Total Blocks: 4
Total Time: 2.4sec
Anyways, I’m sure there is a hundred other ways you could get better results — but this might be good enough for small quick measurements.
ERROR: Cacographic Solecism Directive Encountered **
** Unreadable Error Message Found
I’m pretty picky about user interface with a lot of the projects I work on ranging from the user experience to the design and layout. Ever since I read Steve Krug’s, Don’t Make Me Think, I find myself spending a lot of time reading over the same content again and again trying to simplify them to their shortest possible length.
One section that has always been a focal point for me has been error messages or really any dialog that requires user interaction. However, I’m not just talking about the cryptic, developer designed error messages like ‘IOError Detected!’ or ‘Generic GDI+ Error’ (I especially hate that error).
No, the error messages I’m talking about are messages that don’t really help the user — or error messages that help the user, but too late into the message.
Here is an example from Netflix. It isn’t a bad message but I think that it could be improved.

The Anatomy Of An Error Message
Not all situations are the same but I try to write all of my error messages in the following order.
- What happened in a short sentence.
- Give the user options and solutions
- Explain in slightly more detail what happened but only if the problem may happen again or it helps them understand how to avoid the problem.
What Happened? Few Words Should Say It All — Or Don’t Bother!
I try to stay brief with everything… well, except blog posts, of course. If you’ve visited my latest project CustomWebmail.com then you’ll notice I try to keep everything to a sentence or two. I’ve had a lot of feedback that people like how short and to the point everything is.
Your error message should be the same – short and to the point. Don’t waste a lot of time explaining why it broke or telling them what happened in the background that caused the failure.
In some cases you don’t even need to present the problem as an error message especially if the resolution is simple. The Netflix message is a good example of this. The message feels a lot like an error – but should it? Or should it be presented that this message is the natural result of leaving the page idle?
User Options – Empower The User Quickly
Giving the user the control to fix the problem right away should immediately follow the title of the error – not an explanation of the problem. Include only as many options are really relevant.
I’d even go as far to say that even Yes and No buttons should have a description as well. Explain what the yes and no buttons will do — even if it seems obvious. A button that reads “Yes; Save my document to the server” is much clearer than simply a button that says “Yes” or “OK”.
The Netflix error says to reload the page — manually. Why? Chances are they already have a mouse nearby — why not simply say Click Here To Continue Your Movie! and handle reloading their page when they press the button?
They do offer a suggestion but they don’t offer to do it for you, which I think would improve this box a little more.
Explain The Problem: But Only If It Matters
I’m sure this part would be a point of contention to many people. Often we feel like we need to tell the user what is wrong but also why there was a problem. Clearly, each situation is different, but more often than not I think that the ‘why’ is irrelevant. Here are a few times I think explaining why is important.
- The user might make the same mistake again (ex. invalid e-mail addresses)
- The problem might make a user think your service is broken and you need to explain that it is either normal procedure or a problem from somewhere else.
- To answer why a response is required (ex. input form that wants information a user might not be comfortable in providing)
More or less, if the reason why doesn’t affect the user then you don’t need to share it. If your function SaveUserData() crashes and returns an ‘Unable to save to /Data/Profiles/Users.txt’ error then don’t tell your user. Simply saying ‘We’re sorry – We had a problem saving your information’ is more than enough information to explain why they need to do the same step twice.
My Version
Remember, I like to nitpick this kind of thing. I realize that error messages in my own programs could be improved as well. That said, here is a sample that I think would work better for visitors.

With this message, we are to the point faster and offer a solution to the problem immediately. I also dimmed the error message some and highlighted the actions that could be taken so the user would be drawn to it quickly. I’m sure this message could be improved upon even more but this seems like a good start.
How much time do you spend making your messages as short and as simple as possible?
** The author spends a lot of time reviewing content — but not his own blog — so if you see any typos then please be forgiving
Creating CustomWebmail.com – Part 1
CustomWebmail.com is a website that allows you to to create a custom login page for your Outlook Web Access by making changes to the colors, logo and layout of the page. This is a series of blog posts that discuss some of the more interesting parts of developing this project.
The Key Parts Of CustomWebmail.com
In order to develop CustomWebmail.com I had solve a few problems…
- What is the correct address to post logon attempts to?
- How can I be reasonably certain that the address is correct?
- How do I create their custom OWA page with the correct colors and logo?
- What is the best way to convert an theme image into an actual HTML web page?
- How can I package their content into a single .zip file?
For the next few weeks I’ll be going over all the steps I used to allow visitors to create custom Outlook Web Access pages with this site.
Determine The Correct Address
Now, this part is probably not close to perfect yet. As it turns out OWA isn’t standard across the board. I’m not just referring to OWA 2003 compared to OWA 2007 — but even matching versions can have different setups. With that said, the application still needs to come up with the correct postback URL to for the final rendered page.
Asking the visitor for the correct URL is probably not really a good idea. They might not understand where to look inside the form or what the address should look like. Instead, the application simply asks them for the address of the Outlook Web Access login page and then uses a series of HTTP calls to determine the rest.
string path = "http://webmail.example.com/exchange";
HttpWebRequest request = HttpWebRequest.Create(path) as HttpWebRequest;
request.UserAgent = USER_AGENT;
request.CookieContainer = result._Cookie;
//get the response from the requester
response = request.GetResponse() as HttpWebResponse;
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
content = reader.ReadToEnd();
}
//use content to determine form related information
//...
This section of code tells us a few things…
- Did a server respond to our request?
- Were we redirected to a different URL?
- Which level of security was used – http or https
- If the server doesn’t respond was it really because nothing was there?
- Does the content contain anything that looks like an Outlook Web Access page?
- Are we sure that this address will accept our login attempts?
Yikes! Unfortunately those are all real problems that need to be solved in the code — and anything unsuccessful needs to be reported back to the user (or repaired on its own). I’ll skip over the first three since they are fairly easy to determine.
Exception With A Responding Server?
I’ve found that with the HttpWebRequest sometimes you get an exception even if the server is found because the certificate at the site isn’t valid. It throws you off quite a bit especially if you’re expecting a response and your code simply crashes.
As it turns out it isn’t hard to handle invalid certificates.
//Ignore bad certificates
// ** Use at your own risk **
ServicePointManager.ServerCertificateValidationCallback = (obj, cert, chain, ssl) => {
return true;
};
In my case I’m not too worried if the server’s certificate is valid – I just want to know if it is responding to my requests. By adding in this line of code I can ignore anything invalid and move forward.
Just What Is This Page Anyways?
There are a few arguments you need to use when posting back to an Outlook Web Access login page. We wouldn’t want to accidentally create a login page if someone entered ‘google.com’ instead. By using a couple Regular Expressions we can check to see if the form looks like an Outlook Web Access page.
Here are some of the fields you can check for…
- An input named username
- An input named password
- An hidden input named destination
- An form action to something containing owaauth.dll
There are more fields you can use but these tend to be a fairly sufficient indicator if we’re looking at an Outlook Web Access form.
Testing The Login
At this point we’re fairly confident that the server we are looking at is an OWA login page but there is one more test we can try. In the final test we perform a fake login to the page to see if we get a password failed error response.
//test the target of the form that was found
HttpWebRequest request = WebRequest.Create(formTarget) as HttpWebRequest;
//create the standard postback information
string post = string.Format(
"username={0}&password={0}&forcedownlevel=0&trusted=0&flags=0&destination={1}&isUtf8=1",
DateTime.Now.Ticks,
HttpUtility.UrlEncode(this.Destination)
);
//prepare the request
request.MaximumAutomaticRedirections = 10;
request.UserAgent = USER_AGENT;
request.Method = "POST";
request.Timeout = 15000;
//and add the content
using (StreamWriter writer = new StreamWriter(request.GetRequestStream())) {
writer.Write(post);
}
//get the login attempt result
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
response = request.GetResponse() as HttpWebResponse;
//check if a reason code was included
return Regex.IsMatch(response.ResponseUri.Query, @"(&|\?)?reason=\d", RegexOptions.IgnoreCase);
It is possible that we just happened to come across a random server that returns a response code but given all the other tests we can be fairly confident in the address we’re testing.
As a final option we present the user with a test login box that they can try to do a personal verification that the address works.
Introducing CustomWebmail.com
I like blogging but the past few weeks (maybe months?) my posts have gotten a little sparse — but for good reason! I’ve been working hard on completing another project and this weekend was the launch date!
What Is CustomWebmail.com?
I do a lot of contract work ranging from programming applications to fixing other in-house developed applications. One job that always gets a lot of interest is customizing a corporate Outlook Web Access login page. I’ve done several of these for a variety of companies.
The idea behind the website was to move the entire customization process online and then present the user with a nice neat .zip file of the resources they would need to install on their webmail server.

How It Was Made
The site uses ASP.NET MVC, C# and jQuery — I couldn’t find a use for my jLinq project, unfortunately
. The site does a lot of interesting things in the code like checking remote sites via HttpWebRequest or creating HTML and image slices using the System.Drawing classes. Over the next few weeks I’ll go over some of the more interesting parts of how the site works.
For now, if you have any Server Admin buddies that might be interested, please tell them about http://www.CustomWebmail.com.
Render Partial — But With Arguments!
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.
Spelling It Out With Booleans
Code complexity has been a big issue for me lately. I’ve been realizing that the quality of my code has degraded over the years to the point that I’m finding I cram large chunks of code into a vaguely named method like Load() or Render(). It wasn’t until I got an assistant and I likened programming to ‘painting by number’ that I realized that I wasn’t following my own instructions anymore.
It wasn’t that I was intentionally writing complex code but rather that a large complex function wasn’t hard to read anymore — my definition of complexity has changed.
The last time that I discussed code complexity I explained that writing short, clear methods was an ideal way to decrease code complexity. This post continues the discussion by looking at using booleans to improve the readability of code.
Clarity With Booleans
Maybe you’ve seen a snippet of code like this before…
if (value % 2 == 0) {
//do something
}
else {
//do something else
}
Most programmers are going to immediately recognize what this code is going to do — but imagine for a second that you don’t know what that code does. How is a less seasoned programmer going to have any clue what just happened there? Try Googling ‘value % 2 == 0′? I don’t think that is going to work out so well.
This is a good example where a boolean can be used to create clarity in a program. A boolean is used to determine the flow of a program — so why not use well named booleans to further clarify your intent?
bool isEvenNumber = (value % 2 == 0);
if (isEvenNumber) {
//do something
}
else {
//do something else
}
This is a simple example but it applies everywhere. What stops you from spelling it out with a boolean?
Describe Intent Without A Comment
MVC is a good example of where well named booleans can improve the readability of code. How much harder is the first snippet to read compared to the second.
Logic Performed Inline
<div class="<% if (allItems.IndexOf(entry) % 2 == 0) { %>alt-item %<% } %><% if (entry.DatePosted.Date < DateTime.Now.Date.AddDays(-7)) { %>old-post<% } %>" >
<div class="subject" ><% =entry.Subject %></div>
<% if (string.IsNullOrEmpty((entry.Location ?? string.Empty).Trim())) { %><div class="location" ><% =entry.Location %><% } %>
<% if (string.IsNullOrEmpty((entry.Description ?? string.Empty).Trim())) { %><div class="desc" ><% =entry.Description%><% } %>
</div>
Logic Performed In Advance
<%
bool isEvenItem = (allItems.IndexOf(entry) % 2 == 0);
bool olderEntry = (entry.DatePosted.Date < DateTime.Now.Date.AddDays(-7));
bool hasLocation = (string.IsNullOrEmpty((entry.Location ?? string.Empty).Trim()));
bool hasDescription = (string.IsNullOrEmpty((entry.Description ?? string.Empty).Trim()));
%>
<div class="<% if (isEvenItem) { %>alt-item %<% } %><% if (olderEntry) { %>old-post<% } %>" >
<div class="subject" ><% =entry.Subject %></div>
<% if (hasLocation) { %><div class="location" ><% =entry.Location %><% } %>
<% if (hasDescription) { %><div class="desc" ><% =entry.Description%><% } %>
</div>
Snippet one is much shorter than snippet two — but does that really make it better? Or less complex?
You could argue that the logic shouldn’t be inline with MVC to begin with and you’d be correct. Instead those same comparisons would be well named boolean properties attached to the the model being used — which is exactly what I’m suggesting here.
It doesn’t matter where they are but using well-named booleans can improve and clarify the flow of logic in your application.



