Hooking up The Lounge - seems like a perfect fit

, , No Comments »

The Lounge

I was noticing the traffic on the site for Spark project information and documentation has been picking up nicely. That lead me to thinking about bumping up to another notch on the slice size, but that sort of doubles the hosting cost. It’s pretty modest figure but it can add up over the year.

With the hosting costs at the top of my mind I noticed that a number of the blogs I’ve been reading like Haack’s, Hanselman’s, and Felker’s are showing ads from The Lounge. The ads seemed pretty topical too, relating to a tight cluster of dotnet development and web hosting subject matter, so I dropped them a line to see if the volume of traffic I had was on their radar.

Turns out they do have an advertising bundle of open source product sites, like Ninject, which Spark fit into quite nicely. One day later everything’s all hooked up and running.

It’s nice to have a little splash of color on the page too. I didn’t realize it at the time (paging through all of the Drupal themes of all shape and color) but that particular theme is pretty stark on pages where the blue info block isn’t present.

Spark v1.0 and presentation for MPLS ALT.NET

, , , , 4 Comments »

The first news is that the Spark v1.0 bits are now officially released and are the default download at CodePlex. It re-opens the gates to more substantial changes that have been postponed for the release milestone.

Spark View Engine Coinciding with the release I did a presentation of Spark on the 18th for the Minneapolis ALT.NET group organized by Freemind.

I had mentioned I was preparing for this and someone on Twitter asked if it would be recorded, so I arranged for a camcorder to be present.

Downloadable materials:
PowerPoint slides
All files and projects
New Downloadable version at 1024×768, 982.21MB

Spark View Engine Spark View Engine

Spark View Engine Spark View Engine

Spark View Engine Spark View Engine

Spark View Engine Spark View Engine

There were some lessons learned. One is that CamStudio will record as long as you like, then fail when it’s compressing and interleaving audio if the result is larger than 4GB.

Fortunately, out of a deep-seated (and apparently justified) distrust of technology there was also a camcorder on a tripod. An Avisynth filter named Reform provided some fairly acceptable results reconstructing a 4:3 aspect ratio of the screen.

There is an additional 30 minutes of audio captured by CamStudio after the tape ran out. I’m thinking of recapturing a video to go with that.

ViewData Dictionary vs. View typed Model

, , , , 9 Comments »

This post exists because trying to explain something 140 characters at a time makes you sound insane.

Earlier Brad Wilson speculated:

Theory: in ASP.NET MVC, master pages cause users to use ViewData instead of strongly typed models more often than any other reason.

To which I replied:

@bradwilson That, plus keeping properties in sync on a class that exists only to stand between an action and view isn’t very DRY

It’s true there are a huge number of reasons to need data in a master layout like navigation, sidebar widgets, current user profile, ad codes, etc. But if that was the main cause should be pretty easy to address by having the master layout’s data in a layer superclass for all of your action-view models.

I believe another even more serious problem is the view model can make you repeat yourself a huge number of times.

One of the things that’s really nice about actions on a controller is you can avoid the proliferation of classes you get with the command pattern. If you make a model for each action you get that problem back in spades. You could keep track of commonality between actions to reduce the number of action/view model classes, but that’s more work and you’re playing a balancing act between how many classes you are making and how many unused properties are acceptable for actions that don’t produce strictly identical data.

Plus it’s not DRY… I’ve added the action to a controller, then I need to add the class to hold the data. I’ve acquired some data in the action, then I need to add the typed property to the action’s model. Some data’s refactored out of the action, then I need to remember to remove it from the data bucket class too.

Just to throw an idea out there, to have a DRY action-view model class, how about adding the idea of a dynamic partial class to the language? A partial class which merges with additional auto-implemented properties at compile-time, as a result of the property assignments on that type.

So here’s that you would have today. The following assumes DefaultMasterData members will be assigned by filters if the model has an appropriate base class.


public class DefaultMasterData
{
	public UserProfile Profile {get;set;}
	public string AdvertisementCampaignCode {get;set;}
}

public class HomeIndexData : DefaultMasterData
{
    public Product Product {get;set;}
	public Order CurrentOrder {get;set;}
}

[UserProfileFilter]
[AdvertisingFilter]
public class HomeController
{
    public ActionResult Index()
    {
		...acquiring stuff here...

		// return view of model
	    return View(new HomeIndexData {Product = mostRecentProduct, CurrentOrder = activeSessionOrder});
    }
}

Here’s if you had a dynamic partial class. The assignment of non-existant properties results in an implicit partial with auto-implemented properties to be merged in at compile time.


public class DefaultMasterData
{
	public UserProfile Profile {get;set;}
	public string AdvertisementCampaignCode {get;set;}
}

public dynamic partial class HomeIndexData : DefaultMasterData
{
}

[UserProfileFilter]
[AdvertisingFilter]
public class HomeController
{
    public ActionResult Index()
    {
		...acquiring stuff here...

		// return view of model
		// creates implicit partial with auto-implemented properties
	    return View(new HomeIndexData {Product = mostRecentProduct, CurrentOrder = activeSessionOrder});
    }
}

And to kill just a bit more code, how about a the ability to declare the named type without the empty class statement?


public class DefaultMasterData
{
	public UserProfile Profile {get;set;}
	public string AdvertisementCampaignCode {get;set;}
}

[UserProfileFilter]
[AdvertisingFilter]
public class HomeController
{
    public ActionResult Index()
    {
		...acquiring stuff here...

		// return view of model
		// creates implicit partial with auto-implemented properties
		// also results in the initial declaration of the type HomeIndexData based on DefaultMasterData
	    return View(new dynamic partial HomeIndexData:DefaultMasterData
	        {Product = mostRecentProduct, CurrentOrder = activeSessionOrder}
	    );
    }
}

There! Now I think you’ll see people using a base of ViewPage<HomeIndexData> in Index.aspx.

Clearly there are lots of questions about namespace, etc., but you get the idea.


Final note, to declare an anonymous type with a base class, it would be nice to support something like.

var x = new :MyBase {Foo="bar", Frap=5};

Another final note - you wouldn’t need to do it all inline of course.


[UserProfileFilter]
[AdvertisingFilter]
public class HomeController
{
    public ActionResult Index()
    {
	    var model = new dynamic partial HomeIndexData:DefaultMasterData();

		...acquiring stuff here...

		// assignments causing more auto-impl props here
	    model.Product = mostRecentProduct;
	    model.CurrentOrder = activeSessionOrder;

		// return view of model
	    return View(model);
    }
}

Using Live Mesh and Git - the best of both worlds

, , , 11 Comments »

I like Live Mesh. I like Git, too.

If you’ve used a folder synchronizing tool before that will propogates file changes between machines, like FolderShare or DropBox, there’s a good chance you’ve had a scare with some possible data loss. Maybe you accidentally dropped a folder into a subfolder, “made space” by getting rid of files on one of the machines, or the sync software went crazy. Whatever the case is the change is immediately shipped onto all of your backups all over the world.

That effect makes file sync tools more of a convenience than a backup strategy - it can lower your mean time to recovery in case of hardware failure - but even though there are two or more physical copies of your bits there’s really one logical copy that appears in several places where it can be accidentally deleted. Ironically the convenience of having your data everywhere also lowers it’s mean-time-to-accidental-destruction.

Which is exactly the problem a change control repository like Git is designed to solve! Fearing data loss as much as the next person, I tried to combine the convenience of Live Mesh with the safety of Git and it worked really well. Here’s how it went, assuming you have msysGit and Live Mesh installed on your machine.
Read the rest of this entry »

Starting with Spark in ten minutes

, , , No Comments »

Earlier today Donn Felker blogged about his new DimeCast episode:

# 113 - Saying Hello to the Spark View Engine

In this episode we are going to start a series where we take an indepth look at the Spark View Engine.

Spark is a view engine for Asp.Net Mvc and Castle Project MonoRail frameworks. The idea is to allow the html to dominate the flow and the code to fit seamlessly.

Very cool. Can’t wait to see it on a pc with audio.

It also reminds me I need to revamp the front page of the project site. I’d like for it to start with something like a quick article about creating a spark app instead of a bunch of random links.

Spark Macro for Uploadify, Take One-B

, , 8 Comments »

Matt recently wrote in ASP.NET MVC HtmlHelper for Uploadify, Take One about a fairly common problem in the shades of gray where html and code concerns overlap. It’s a game of trying to get the least of both evils mixed in with the other.

Matt makes a particularly insightful remark in a comment, “what I dislike is how the balance of language in the helpers tends to shift from C# to JavaScript or HTML.”

I’d agree with that. On the one hand you’re trying to avoid excessive code in your template, but in doing so you’re dragging markup into your code. It’s actually a great example of a primary use-case for a macro in the Spark language, which lets you declare a helper method in the template language.

Here is the HtmlHelper extension exactly as it appeared on Matt’s post:

/// <summary>
/// Renders JavaScript to turn the specified file input control into an
/// Uploadify upload control.
/// </summary>
/// <param name="helper"></param>
/// <param name="name"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string Uploadify(this HtmlHelper helper, string name, UploadifyOptions options)
{
    string scriptPath = helper.ResolveUrl("~/Content/jqueryPlugins/uploadify/");

    StringBuilder sb = new StringBuilder();
    //Include the JS file.
    sb.Append(helper.ScriptInclude("~/Content/jqueryPlugins/uploadify/jquery.uploadify.js"));
    sb.Append(helper.ScriptInclude("~/Content/jqueryPlugins/uploadify/jquery.uploadify.init.js"));

    //Dump the script to initialze Uploadify
    sb.AppendLine("<script type=\"text/javascript\">");
    sb.AppendLine("$(document).ready(function() {");
    sb.AppendFormat("initUploadify($('#{0}'),'{1}','{2}','{3}','{4}','{5}',{6},{7});",
                    name, options.UploadUrl,
                    scriptPath, options.FileExtensions,
                    options.FileDescription, options.AuthenticationToken,
                    options.ErrorFunction ?? "null",
                    options.CompleteFunction ?? "null");
    sb.AppendLine();
    sb.AppendLine("});");
    sb.AppendLine("</script");

    return sb.ToString();
}

And here’s the same helper implemented as a macro:

<macro name="Uploadify" name="string" options="UploadifyOptions">

  <var scriptPath="Html.ResolveUrl('~/Content/jqueryPlugins/uploadify/')"/>

  !{Html.ScriptInclude("~/Content/jqueryPlugins/uploadify/jquery.uploadify.js")}
  !{Html.ScriptInclude("~/Content/jqueryPlugins/uploadify/jquery.uploadify.init.js")}

  <script type="text/javascript">
    $(document).ready(function() {
      initUploadify($('#!{name}'), '!{options.UploadUrl}',
        '!{scriptPath}', '!{options.FileExtensions}',
        '!{options.FileDescription}', '!{options.AuthenticationToken}',
        !{options.ErrorFunction ?? "null"},
        !{options.CompleteFunction ?? "null"});
    });
  </script>

</macro>

The usage of the helper remains nearly identical. It’s a method on the view now instead of an Html extension method… So:

<%= Html.Uploadify("fileInput", new UploadifyOptions { ... }) %>

becomes:

<%= Uploadify("fileInput", new UploadifyOptions { ... }) %>

or rather:

!{Uploadify("fileInput", new UploadifyOptions { ... })}

Server upgraded - brief service interruption

, , , No Comments »

The host this runs on was upgraded just now. Runtime for the VM Ubuntu host was 399 days. Hats off to slidehost for that quality of service!

Upgrade went well - some config files showed up as modified so there were some keep/replace prompts. But in general pretty smooth.

Did lose the php-fastcgi daemon in the upgrade though. So that was a bit of a rough moment after the reboot when both http://whereslou.com and http://sparkviewengine.com were toast.

Fortunately a quick Google search turned up this blog post from Elderec which got me up and running again.

Spark in the field - MarketWatch 5.0

, , 1 Comment »

The MarketWatch site has recently recently been the target of a massive renovation project. A highlight of some new features from an editorial perspective can be found at the Site tour, but I wanted to take some time to talk about it from a technology point of view.

The initial work for engineering began some time last year, approximately December, we began to create systems known to be necessary for the functionality that would be eventually required. The middle of the first quarter saw the completion of the joint efforts of the design agency and business stakeholders in the form of new IA/UX and design. With an ultimate target date of May 12th I’m sure you can appreciate the fact a huge number of things about the implementation needed to go very well.

Many people on several teams were involved in it’s creation. I can’t possibly name everyone involved but I wanted to recognize a few people who acted in a technical leadership capacity.
Read the rest of this entry »

Recipe for Spark build/dev machine on Virtual PC

, , , 1 Comment »

I had a Virtual PC instance die recently. Oddest thing - it wouldn’t accept network traffic anymore. If it wasn’t virtual I’d have assumed it was a hardware problem.

I need to create an RC2 build of Spark, so I need to recreate a suitable platform. To kill two birds with one stone I thought I would keep track of the software I installed to be able to run the Spark distribution build.
Read the rest of this entry »

Clean blend of javascript and csharp

, , 1 Comment »

Just came across this code which I thought looked remarkably clean, considering how bad this type of thing could normally turn out.

This is including a small inline javascript at the tail of the layout. A dictionary in viewdata contains any number of key/value pairs that are passed to Omniture.

<viewdata OmnitureValues="Dictionary[[string, object]]"/>
<script type="text/javascript" language="JavaScript" src="http://www.example.com/include/js/s_code.js"></script>
<script type="text/javascript" language="JavaScript">
if (typeof s != "undefined")
{
# if (OmnitureValues != null)
# {
#   foreach (var val in OmnitureValues)
#   {
      s.${H(val.Key.ToLowerInvariant())} = "${H(val.Value)}";
#   }
# }

/************* DO NOT ALTER ANYTHING BELOW THIS LINE ! **************/
var s_code=s.t();if(s_code)document.write(s_code) }//
</script>

The lines starting with hash (#) marks are server-side code. The innermost line ends up being written out in the script once for each key/value pair. The thing I thought was so striking was how I scanned and grokked what the function was doing before I even realized I was looking at a mix of inline javascript and csharp.

So good job to the programmer that did this one. :)

Design by j david macor.com.Original WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in