MsCorEE

JeffGonzalez : IScalable

March 2007 - Posts

MSBuild, MbUnit 2.4 and CruiseControl.NET
Getting all of these technologies synced up was pretty neat to see in
action. I hadn't really done much more than a very vanilla
installation of CruiseControl in the past. I have had a good chunk of
time to dedicate to this project so I wanted to add some bells and
whistles.

At first getting MSBuild and MbUnit to place nicely was a challenge.
For whatever reason, unless you have the MbUnit dlls in the framework
folder and in the bin folder where your test dll is located, MSBuild
will not execute the MbUnit task correctly.

It feels like a hack, but I guess I can live with it. I do hope it
gets some attention in a future release of MbUnit, but if I understand
the problem correctly, it might have to wait for a bit.

I ended up writing this utility MSBuild target to make sure this got
done during a build. This target checks to see if the each of the
MbUnit files needed to execute properly is not present in the
Framework folder. If it isn't found (this condition is only satisfied
on the very first run of the build), we copy the files to the
framework folder.

<Target Name="CopyMbUnitToFramework">
<Copy SourceFiles="$(LibraryFolder)\$(MbUnitFrameworkDll)" DestinationFiles="$(FrameworkPath)\$(MbUnitFrameworkDll)" Condition="!exists('$(FrameworkPath)\$(MbUnitFrameworkDll)')"/>
<Copy SourceFiles="$(LibraryFolder)\$(QuickGraphDll)" DestinationFiles="$(FrameworkPath)\$(QuickGraphDll)" Condition="!exists('$(FrameworkPath)\$(QuickGraphDll)')"/>
<Copy SourceFiles="$(LibraryFolder)\$(QuickGraphAlgorithmDll)" DestinationFiles="$(FrameworkPath)\$(QuickGraphAlgorithmDll)" Condition="!exists('$(FrameworkPath)\$(QuickGraphAlgorithmDll)')"/>
<Copy SourceFiles="$(LibraryFolder)\$(ReflyDll)" DestinationFiles="$(FrameworkPath)\$(ReflyDll)" Condition="!exists('$(FrameworkPath)\$(ReflyDll)')"/>
<Copy SourceFiles="$(LibraryFolder)\$(TestFuDll)" DestinationFiles="$(FrameworkPath)\$(TestFuDll)" Condition="!exists('$(FrameworkPath)\$(TestFuDll)')"/>
</Target>

Once I had MsBuild and MbUnit successfully integrated, it was a simple
matter of merging the report xml from my tests into the ccnet server
config.


[tags: msbuild, mbunit, cruisecontrol,continuousintegration continuous
integration, ccnet, cruisecontrol.net]

Problems updating an svn:External in Subversion using https/ssl via CruiseControl.Net
I have been diligently working on the build process here at work and I
ran into an interesting problem. There is plenty of information on
the matter on Thoughtworks website, but I wanted to post it here as a
reference.

The problem is an interesting one, I don't know if I can explain it
well enough, but I will try.

We have a couple of dependencies on third party files in our product.
These third party files are part of our source code repository via a
feature called Externals. I would say this is somewhat equatable to a
symlink for Subversion. We can reference a different subversion
repository as a directory in our repository.

Suppose I have a repository like this:

svnroot
trunk
MyCoolCode

I put all of my local project files into the "MyCoolCode" directory.
Let's say someone has a really cool utility library that I want to
include in my project as well. There are several options, but
svn:Externals allows me to check out the code from a remote repository
down into my local files. This makes managing the consumption of an
external project much easier.

Back to the problem....I happen to be pulling this external codebase
from an svn repository that is over https. So when I execute the svn
update command from a command line for the first time, I get a warning
or prompt stating that I need to either Reject, Accept Temporarily or
Accept permanently the https certificate. This is all fine and dandy
and it works when I do it manually, but my ccnet service is currently
running under the LocalSystem account. I am just testing some things
out with the build process in general, normally I would create a
service account to run it under. What I ended up having to do was
launch a cmd.exe running under the LocalSystem account and then run
the svn update command again and permanently accept the http
certificate.

A bit of a beating if you ask me. The links below made it pretty easy
to solve the issue.

http://confluence.public.thoughtworks.org/display/CCNET/Subversion+Source+Control+Block?showComments=false
http://confluence.public.thoughtworks.org/display/CCNET/The+Server+Service+Application
http://blogs.msdn.com/adioltean/articles/271063.aspx

[tags:subversion, svn, external, externals, build process, build,
ccnet, cruisecontrol.net, http, ssl]
Install Vista from USB Key

[tags: vista, install vista, usb]

This is pretty sweet: http://kurtsh.spaces.live.com/blog/cns!DA410C7F7E038D!1665.entry

I was able to use vsLite(http://www.vlite.net/) to trim my vista install down to around 1200 MB.  It took 13:51 minutes from the start to finish to install Vista just the way I like it.

Posted: Mar 28 2007, 05:34 PM by likwid | with 1 comment(s)
Filed under: , ,
My new-new job

I almost forgot...I start my new job tomorrow.  It is at a little place you might have heard of...


CodeSmith Tools!

Eric and I have been wanting to work together for awhile now, but the timing always seemed off.  I am excited to be working there, not only do I get to sponge knowledge off Eric's greatness, but we are in the same offices as Telligent, so I should be working in the vicinity of some really smart people.

I also am getting reunited with my boss from my last job, Shannon (still no blog, I'll keep working on it), so it should be a blast. 




 

Posted: Mar 25 2007, 08:31 PM by likwid | with 1 comment(s)
Filed under: ,
Anonymous methods, generics and bears...Oh my
I stumbled across an interesting conversation on Jeff's(I am not speaking in the third person, this Jeff) blog.  Like any other time, I have plenty to say on the matter....

Microsoft (via FxCop) suggests that you don't expose List<T> via public members.  I think the reasons I have heard mentioned in the past are around versioning your collections and the API for List<T> being too large for public APIs.

While I don't agree with Ramon's random "suggestions" about language fluency, I do think he makes a good point about losing the flexibility of generic types by making a class directly inherit from List<T>.  With the current example (I realize this may or may not be contrived), following that route would require you to create a collection class for each class in your project. 

I suppose you could do 1 of 2 things (if you were so inclined):

Create a generic type that inherits from list<T>, which is pretty close to what you have.  Only a slight modification need be made:

public class GenericList<T> : List<T>
{
}

Or you could create a generic type that implements List<T> as an inner list and expose only the stuff you need from List<T>. 

public class GenericList<T>
{
    private List<T> _innerList;

    public MyListTwo()
    {
        _innerList = new List<T>();
    }

    public void Add(T obj)
    {
        _innerList.Add(obj);
    }

    public T Find(Predicate<T> pred)
    {
        return _innerList.Find(pred);
    }
}
(This one has my vote).

Either of these would accomplish the same thing, but without the loss of flexibility.

As for the complexity of the anonymous methods, I don't think it is bad looking at all for very simple things, most of the time you are just wanting to get an item or a series of items based on a particular property.  I do think for complex things, you should go ahead and make a method that encapsulates all of the logic for the particular predicate.
Model View Presenter Redemption

I just wanted to clarify that I figured out my issue with the databinding.   Rookie mistake, I forgot to wrap OnItemDataBound with ItemType check.  I can't believe I missed that.  Thanks to members of the Faithful 21 (The endearing term for all of my 21 readers =P)
 

Sorry, I forgot to post the solution:

void CustomerRepeaterCodeBehind_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    switch(e.Item.ItemType)
    {
         case ListItemType.AlternatingItem:
         case ListItemType.Item:
            RepeaterItem item = e.Item;
            Customer c = item.DataItem as Customer;
            Label nameLabel = e.Item.FindControl("NameLabel") as Label;
            nameLabel.Text = c.Name;
            break;
    }

It does sort of beg the question on how to handle this scenario.  I mean if the View is supposed to be lightweight and you have to write custom databinding logic, it seems like you lose the testability aspect of the view.  I haven't figured this part out yet, if anyone has any experience with it or has read about this kind of case (which is pretty common in my world) I would love to hear about it.

Thanks! 

Model View Presenter Woes

Jumping on the bandwagon for Model View Presenter.  It is something I have been intrigued with for quite awhile, but I am just getting around to implementing it.

How come almost all of the examples for MVP are the absolute most basic thing you can think of.  Most of them seem to be edit pages also.  I get that you put properties on your View and then set those from the Presenter, but what about list pages?  Those don't seem to get enough attention.

So I set about trying to implement a list page today and I ran into a showstopping issue.  I searched around and it seems like a lot of people have had this same issue, but I don't see it really being addressed in the way I am thinking.

What I am trying to do is use the ItemDataBound method of my repeater for listing out the obligatory Customer entity.  Sorry, I am an unoriginal *** and I couldn't think of anything clever.  So I created a view ( ICustomerListView ), a presenter ( CustomerListPresenter ) and an entity ( Customer ).

When I use declarative databinding on the repeater, this pattern works fine.  Unfortunately, I am in a situation where I cannot use declarative databinding.  At my new job their architecture is based around everything being in the CodeBehind and while I don't necessarily agree with it, I do understand the apprehension against it.  Pretty soon you end up putting a lot of display logic into your aspx page and it can get a little messy.  The problem I am running into happens in the ItemDataBound method.  It acts like it cannot see the items in the repeater, which is odd, because it is firing the ItemDataBound event.  It is almost like it fires the event and then loses all knowledge of having items in the repeater.  Here is the code, I have tried to keep it short, maybe someone smarter than me can point out my n00bish error.

View:
namespace JeffGonzalez.SupervisingController
{
    public interface ICustomerListView
    {
        List<Customer> Customers { set; }
    }
}

Presenter:
namespace JeffGonzalez.SupervisingController
{
    public class CustomerListPresenter
    {
        private ICustomerListView _View;

        public CustomerListPresenter(ICustomerListView view)
        {
            _View = view;
        }

        public void UpdateView()
        {
            List<Customer> list = new List<Customer>();
            list.Add(new Customer("ABC Customer"));
            list.Add(new Customer("DEF Customer"));
            list.Add(new Customer("GHI Customer"));

            _View.Customers = list;
        }
    }
}

CodeBehind:
namespace JeffGonzalez.SupervisingController
{
    public partial class _Default : System.Web.UI.Page, ICustomerListView
    {
        private CustomerListPresenter _Presenter;

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            CustomerRepeaterCodeBehind.ItemDataBound += new RepeaterItemEventHandler(CustomerRepeaterCodeBehind_ItemDataBound);
            _Presenter = new CustomerListPresenter(this);
            _Presenter.UpdateView();
        }

        void CustomerRepeaterCodeBehind_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            RepeaterItem item = e.Item;
            Customer c = item.DataItem as Customer;
            Label nameLabel = e.Item.FindControl("NameLabel") as Label;
            nameLabel.Text = c.Name;
        }

        public List<Customer> Customers
        {
            set
            {
                this.CustomerRepeaterDeclarative.DataSource = value;
                this.CustomerRepeaterCodeBehind.DataSource = value;
                this.CustomerRepeaterDeclarative.DataBind();
                this.CustomerRepeaterCodeBehind.DataBind();
            }
        }
    }
}

 

For brevity I am only including the repeater with the problem, the declarative one works fine, using the <%# Eval("Name") %> syntax:
<asp:Repeater id="CustomerRepeaterCodeBehind" runat="server">
            <headertemplate>
                <table summary="This table displays a list of customers" width="500">
                    <caption>List of customers that can be individually edited</caption>
                    <thead>
                   
                    </thead>
                    <tbody>
            </headertemplate>
            <itemtemplate>
                        <tr>
                            <td><asp:label id="NameLabel" runat="server"></asp:label></td>
                        </tr>
            </itemtemplate>
            <footertemplate>
                    </tbody>
                </table>
            </footertemplate>
        </asp:Repeater>

 So you can see here, I created a label called NameLabel and in the ItemDataBound method of my codebehind/View I want to get that label and set its Text property.  However when I get into this method via debugging, e.Item.FindControl("NameLabel") returns null and e.Item.* returns a nullreferenceexception.  I cannot get to e.Item.DataItem or anything else.  I don't get it....
 

ModalPopupExtender experiences
I ran into a problem today while working with the ModalPopupExtender.  It was a self imposed problem, but it through me for a loop just the same. I made a confirmation modal window.  I have a need for a user to make a decision when they save something to the database. 

So what I did was create a panel like this:

<asp:Panel id="SamplePanel" CssClass="modal-popup" style='display:none;' runat='server'>
<table>
<tr>
<td class="modal-content">
<p>
This is a message detailing a warning.
</p>
<p class="modal-warning">
Do you want to proceed with this action?
</p>
<asp:button id="YesButton" runat="server" text="Yes" cssclass="modal-button"/>
<asp:button id="NoButton" runat="server" text="No" cssclass="modal-button"/>
</td>
</tr>
</table>
</asp:Panel>

This allows the user to choose yes or no, and it sets a hidden form field with this value.  I set up my ModalPopupExtender like this:

<ajax:ModalPopupExtender 
id="ModalPopupExtender"
runat="server"
dropshadow="true"
targetcontrolid="SaveButton"
popupcontrolid="SamplePanel"
backgroundcssclass="modal-background"
okcontrolid="YesButton"
onokscript="onConfirm()"
cancelcontrolid="NoButton"
oncancelscript="onCancel()"/>
 
With this I was able to popup my modal window.  I had to craft some javascript for the ok/cancel stuff still.  I did that by registering a script block from the codebehind (Thanks Shannon!).  Here it is:

private void BuildModalScript()
{
StringBuilder yesScript = new StringBuilder();
StringBuilder noScript = new StringBuilder();

yesScript.AppendFormat("function onConfirm(){0}", Environment.NewLine);
yesScript.Append("{").Append(Environment.NewLine);
yesScript.AppendFormat("var hidden = $get(\"{0}\");{1}", HiddenField.ClientID, Environment.NewLine);
yesScript.AppendFormat("hidden.value = \"true\";{0}", Environment.NewLine);
yesScript.Append(Page.ClientScript.GetPostBackEventReference(SaveButton, String.Empty));
yesScript.Append("}").Append(Environment.NewLine);

noScript.AppendFormat("function onCancel(){0}", Environment.NewLine);
noScript.Append("{").Append(Environment.NewLine);
noScript.AppendFormat("var hidden = $get(\"{0}\");{1}", HiddenField.ClientID, Environment.NewLine);
noScript.AppendFormat("hidden.value = \"false\";{0}", Environment.NewLine);
noScript.Append(Page.ClientScript.GetPostBackEventReference(SaveButton, String.Empty)).Append(Environment.NewLine);
noScript.Append("}").Append(Environment.NewLine);

if (!Page.ClientScript.IsClientScriptBlockRegistered("onConfirm"))
Page.ClientScript.RegisterClientScriptBlock(typeof(_Default), "onConfirm", yesScript.ToString(), true);

if (!Page.ClientScript.IsClientScriptBlockRegistered("onCancel"))
Page.ClientScript.RegisterClientScriptBlock(typeof(_Default), "onCancel", noScript.ToString(), true);
}

When I first started this little project, I was used to faking postbacks using the script like this:  __doPostBack(Control.ClientId);   Oddly that works if you set the enableeventvalidation property to true.  However, it doesn't work if your page is part of a masterpage.  The lead architect, Brian, at my new job and I were banging our heads against the wall trying to figure it out.  He knew there was something in .net that handled this but he couldn't think of the name.  I remembered seeing something like postbackreference during my travels through the documentation.  It turned out to be the correct answer.  I guess you could call it a team effort =P  It was really weird the way the problem manifested itself, because I had two different projects, it worked in one and not the other.  Once I made them exactly the same, we could see there was definitely an issue with master pages.  So chalk that one up to experience.

In any case, I now have a nifty modal confirmation dialog.  Here is the project for vs2005 if you want to take a look.


More Posts