maonet technotes

IOC(SM):MOC(RM):TDD(NU):SCC(TFS):ORM(L2S):JSL(Jq):CIS(CC)

Rewrap Evil ValidationErrors in WPF ValidationRule to enable ajax like validation on WPF Form

Posted by Frank Mao on July 8, 2009

We use Evil Attribute library in our service and UI/ViewModel to do validation on DTO, the big advantage is centralizing the validation rules. One challenge left is how to enable WPF Forms dynamically showing the error message, like ajax doing on web.

Found a very smart and simple solution for this, what we need to do is simply to wrap the Evil ValidationErrors in WPF ValidationRule class.


<Window.Resources>
 <ControlTemplate x:Key="TextBoxErrorTemplate">
 <StackPanel>
 <StackPanel Orientation="Horizontal">
 <Image Height="16" Margin="0,0,5,0"
 Source="warning_48.png"/>
 <AdornedElementPlaceholder x:Name="Holder"/>
 </StackPanel>
 <Label Foreground="Red" Content="{Binding ElementName=Holder,
 Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"/>
 </StackPanel>
 </ControlTemplate>
 </Window.Resources>
 <Grid>
    ...

  <TextBox Height="23" Margin="35,9,77,0" Name="textBox1" VerticalAlignment="Top"
     KeyUp="OnTextBoxKeyUp"
     Validation.ErrorTemplate="{StaticResource TextBoxErrorTemplate}">
     <TextBox.Text>
    <Binding ElementName="listBox1" Path="SelectedItem" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ViewModels:EmailRoleRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
 </TextBox>

public class EmailRoleRule : ValidationRule
 {
  public override ValidationResult Validate(object value, CultureInfo cultureInfo)
   {
   var roleName = (string) value;
   var validator = new EvilValidator(new EmailRoleDto() { Name = roleName });
   if (validator.IsValid())
   {
    return new ValidationResult(true, null);
   }
   return new ValidationResult(false, string.Join("\n", validator.ValidationErrors.ToArray()));
  }
 }

wpf_validation

This technoque is actually described on MSDN.

Here is a post talking about the same skill but takes advantage of tooltips, pretty close to CSLA content control.

Posted in WPF | Tagged: | Leave a Comment »

Popup messagebox in ViewModel

Posted by Frank Mao on July 7, 2009

Very interesting topic, Jeremy’s IMessageBoxService idea is very easy to handle, unit-test. The pain is have to inject this IMessageBox to every class needed.

Glenn Block’s suggestion is using event handler, code can be a little bit cleanner. Test is a little bit harder.


[Test]
 public void should_validate_new_mail_role_and_raise_show_message_event()
 {
    var subscriber = MockRepository.GenerateMock<IEventSubscriber>();
     _emailRoleMaintViewModel.ShowMessageEvent
     += new System.EventHandler<EventArgs<string>>(subscriber.Handler);

     subscriber.Expect(x=>x.Handler( _emailRoleMaintViewModel, new EventArgs<string>("") ))
     .IgnoreArguments();

     _emailRoleMaintViewModel.AddEmailRole("");

     subscriber.VerifyAllExpectations();

 }

More difficult problem is to get the confirmation from view, Glenn’s solution is ‘to raise a separate event to indicate selection which the VM subscribes to‘. Too much overkill for a simple messagebox.

Dong Scott’ s post about CancellableCommand is another option, ViewModel only focus on success logic, but give options to view to ‘cancel’ the action. The comfirmation rending and analyzing code won’t be testable then, but who cares? It’s just a messagebox.


public class CancellableCommand : RelayCommand
{

   public void Execute(object parameter)
   {
   var eventHandler = Executing;
   CancelEventArgs cancelEventArgs = new CancelEventArgs(true);
   if (eventHandler != null)
   {
     eventHandler(parameter, cancelEventArgs);
   }

   if (cancelEventArgs.Cancel) return;

    _execute(parameter);
   }

    public event CancelEventHandler Executing;

}

[Test]
 public void should_stop_if_view_cancel()
 {
 var subscriber = MockRepository.GenerateMock<IEventSubscriber<CancelEventArgs>>();
 _emailRoleMaintViewModel.DeleteCommandObject.Executing +=
 new CancelEventHandler(subscriber.Handler);

 subscriber.Expect(x => x.Handler(_emailRoleMaintViewModel, new CancelEventArgs(true)))
 .IgnoreArguments();

 _emailRoleMaintViewModel.DeleteCommandObject.Execute("");

 subscriber.VerifyAllExpectations();
 _mockLookupProxy.AssertWasNotCalled(x => x.DeleteEmailRole(null), opt => opt.IgnoreArguments());

 }

 [Test]
 public void should_delete_if_view_did_not_cancel()
 {
 var subscriber = MockRepository.GenerateMock<IEventSubscriber<CancelEventArgs>>();
 _emailRoleMaintViewModel.DeleteCommandObject.Executing +=
 new CancelEventHandler(subscriber.Handler);

 subscriber.Expect(x => x.Handler(_emailRoleMaintViewModel, new CancelEventArgs(true)))
 .IgnoreArguments()
 .Do(new EventHandler<CancelEventArgs>(
 (o, e) => { e.Cancel = false; }
 ));

 _emailRoleMaintViewModel.DeleteCommandObject.Execute("");

 subscriber.VerifyAllExpectations();
 _mockLookupProxy.AssertWasCalled(x => x.DeleteEmailRole(null), opt => opt.IgnoreArguments());
 }

Posted in MVP, test | Tagged: | Leave a Comment »

Make WCF client/proxy IOCable

Posted by Frank Mao on July 7, 2009

For unit-test purpose, it’s necessary to make WCF client/proxy class implement from an interface.

The problem is, we suppose to clean up this WCF client after each service call, which means it should be able to repeatedly contracted and disposed. From IOC container we can only get it once. A factory for WCF client is the only solution.

There is an OSS lib from SoftwareIsHardwork. Very detail document.

I personally like Michael Perry’s POCO better:  Client object is created and closed in each service method call, and method is wrapped in lambda expression, very clean and smart.

Posted in IOC, WCF | Leave a Comment »

Twoway databinding selectedItem in WPF listbox

Posted by Frank Mao on July 2, 2009

Found this neat feature from Jonas’ ppt. What a great feature from WPF data-binding! See page 18.

Posted in WPF | Tagged: | Leave a Comment »

Using NHibernate Transformer to get DTO

Posted by Frank Mao on June 30, 2009

I’m slowly adopting Grey Young’s recent topic of CQS – Command Query Separation, sometimes we don’t need a rich domain object for very simple purpose. Most people call it as DTO. Those ‘DTO’ don’t need mapping file. Because they are not translated from domain object, instead they can be ‘transformed’ from NHibernate SQLQuery.

Ayende has an example of SQLQuery using AliasToBeanResultTransformer, here is another example of  PositionalToBeanResultTransformer from Gustavo, which needs add query into mapping file.

I like to keep query out of mapping file, adopt AliasToBeanResultTransformer:


public OrganizationAuditD FindByOrgIdAndAction(long id, string changCode)
 {
 IQuery query = Session.CreateSQLQuery(
 @"select a_Su_Id from dbo.z_Organization_AV  where a_Stakeholder_Id = :id and a_change_code = :changCode")
 .AddScalar("a_Su_Id", NHibernateUtil.String)
 .SetInt64("id", id)
 .SetString("changCode", changCode)
 .SetResultTransformer(new AliasToBeanResultTransformer(typeof(OrganizationAuditD) ))
 ;

 return query.List<OrganizationAuditD>()[0];
 }

My OrganizationAuditD DTO only has one meaningful property: a_Su_Id, that all I need. No other domain property / behavior at all.

Posted in NHibernate | 2 Comments »

WCF PrincipalPermission

Posted by Frank Mao on June 19, 2009

In my previous post, I was using PrincipalPermissionAttribute, the limitation of this solution is, developers have to hardcode the authorized role list into code. To improve it, we can call Demand() method explicitly.


// WCF Service
public void DeleteEmailRole(EmailRoleDto emailRoleDto)
 {
    // Will throw SecurityException and then WCF will convert it to SecurityAccessDeniedException
    // to WCF client side, so we don't need add SecurityException to Contract, because it will not be
    // caught as FaultException.
    AuthorizationChecker.CheckPermissionForCurrentUserOn("DeleteEmailRole");
    EmailService.Delete(emailRoleDto);
 }

public class AuthorizationChecker : IAuthorizationChecker
 {
   private readonly IAuthRoleRepository _authRoleRepository;

   public AuthorizationChecker(IAuthRoleRepository authRoleRepository)
   {
      _authRoleRepository = authRoleRepository;
   }

    /// <summary>
   /// Can be used by UI to enable/disable buttons/menus.
   /// </summary>
   ///
   ///
<param name="serviceName"></param>
   /// <returns></returns>
   public bool IsCurrentUserAllowedTo(string serviceName)
   {
      try
      {
         CheckPermissionForCurrentUserOn(serviceName);
      }
      catch (SecurityException)
      {
           return false;
       }

       return true;
    }

   public void CheckPermissionForCurrentUserOn(string serviceName)
   {
        IPermission permissionSet = null;

        foreach (var role in
          _authRoleRepository.FetchAllRolesHavingAccessTo(serviceName))
        {
            var permission = new PrincipalPermission(null, role);
            permissionSet = permissionSet == null ?  permission : permissionSet.Union(permission);
        }

       // Demand will throw Security exception if user has no permission defined in authRoleRepository.
        if (permissionSet != null) permissionSet.Demand();
     }
 }

// Client code
protected void HandleException(Exception e)
{

   if (e is SecurityAccessDeniedException)
   {
      _messageBox.Show("Sorry you don't have permission to this method.\n" + e.Message);
      throw e;
   }

}

Posted in WCF | Tagged: | Leave a Comment »

Paging fetch result of NHibernate

Posted by Frank Mao on June 17, 2009

Two solutions available for paging fetch result:

  1. SetFirstResult/SetMaxResult when using NHibernate detached queies. Ayende has a good example.
  2. Skip()/Take() when using NHibernate.Linq

I personally like the latter because it’s strongly typed. Performance are same, both with TOP(N) in the generated SQL.

Only issue remaining, how to pass the total count back to service/UI? Options

  1. Using out parameter keyword, as this example.
  2. Create my own Page<T> class to organize the fetch result, similar to the Pager class in Karl’s ModelQuery

Code:  (This one has a double query problem)


public Page<Organization> FetchOrganizationWithNameContains(string orgNamePart
   , int indexOfPage, int resultsPerPage)
{
    var result = new Page<Organization>();

    var query = Session.Linq<Organization>().Where(x => x.Name.Contains(orgNamePart));

    result.Entities = query.Skip((indexOfPage - 1)*resultsPerPage)
        .Take(resultsPerPage).ToArray();

    result.TotalCount = query.Count();

    return result;
 }

Posted in NHibernate | Tagged: | Leave a Comment »

Sending customized error/exception to WCF client

Posted by Frank Mao on June 11, 2009

I was struggling the similar problem as this one, , my customized exception (inherited from exception class) could not be sent to WCF client, once I changed it to regular exception (?) class, it works  as expected. What’s wrong here?

It turns out it was inheritance problem, I missed 2 things: according MSDN guidline (http://msdn.microsoft.com/en-us/library/ms229064(VS.80).aspx)

  1. My customized exception should implement the common ctor accepting (SerializationInfo info, StreamingContext context)
  2. Customized field in my exception needs special storage process done by GetObjectData, and parsing in the common ctor mentioned in 1.

My exception class:


[Serializable]
 public class MyValidationException : Exception
 {
    public IEnumerable<string> ValidationErrors { get; private set; }

    public MyValidationException(IEnumerable<string> validationErrors)
    {
        ValidationErrors = validationErrors;
    }

    protected MyValidationException(SerializationInfo info, StreamingContext context) : base(info, context)
    {
        ValidationErrors = info.GetString("ValidationErrors").Split(new char[]{'\n'});
    }

    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        base.GetObjectData(info, context);
        info.AddValue("ValidationErrors", string.Join("\n",ValidationErrors.ToArray()));
    }

Option B might be to create completely seperate Fault class to re-wrap this exception when doing Converting exception to fault, in which we can take the customized field as ctor parameter to my Fault class.


[Serializable]
public class MyValidationFault : MyBaseFault
{
   public IEnumerable<string> Errors { get; private set; }

   public MyValidationFault(IEnumerable<string> errors, string message)
    : base(message)
   {
     Errors = errors;
   }
}

public static FaultException ConvertExceptionToFault(Exception ex)
{
   if (ex is MyValidationException)
   {
     var vex = (MyValidationException)ex;
     return new FaultException<MyValidationError>(
      new MyValidationError(vex.ValidationErrors, ex.Message)
        , "Validation Failed"
      );
   }

    ...

This disadvantage of creating customized fault solution is, if WCF client use service reference to create client proxy, each proxy will save local proxy types into its own namespace, those common fault classes will be duplicate. It might be a good idea to move those fault into a shared project between server and client.

GenericADOException

Many people start using UoW pattern in WCF by different ways, both Andreas and IgooCoder are using WCF extension. IgooCoder Common removes extension in IDispatchMessageInspector.BeforeSendReply() and then commit  UoW in IExtension.Detach(),  while Andeas commits right in BeforeSendReply.

If exception happens in commit, it won’t be caught by provideFault(), because it’s out of method scope. FaultContract defined at method header doesn’t effect thos commit related exception. They will reach down to UI as general FaultException.

To catch those kind of framework level exception at client side,


protected void HandleException(Exception e){
     if (e is FaultException)
     {
            if( e is FaultException<MyValidationFault>)
            { ...
            }
            else
            {
              _messageBox.Show(((FaultException<ExceptionDetail>)e).Detail.InnerException.Message);
              throw e;
            }
            return;
      }

This means we should only define customized exception in FaultContract.

Posted in WCF | Leave a Comment »

Publish WCF service to clients using different language

Posted by Frank Mao on June 5, 2009

Wcf Test Client tool shipped with SDK (C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\WcfTestClient.exe) is very useful, looks like the WCF request and response is soap-like message passed around. But I have to publish to a real soap web service to enable other language consume Wcf Service, adding an extra endpoint using basicHttpBinding:

<endpoint address=”soap” binding=”basicHttpBinding” contract=”WcfServices.Contracts.ILookupServiceContract” />

My PowerBuilder client can consume this WCF/Soap webservice now:

  1. Add pbwsclientXXX.pbd to lib list.
  2. Use Web Service proxy wizard, generate local proxy for powerbuilder. (My VMWare environment caused lots of trouble, watch out your firewall/router/http proxy)
  3. Code like this:
    
    wcflookupservice lnv_lookup
    gnv_con.createinstance( lnv_lookup, 'wcflookupservice' )
    any list[]
    string email_roles[]
    list = lnv_lookup.FetchAllEmailRoles( )
    
    email_roles = list
    
    int i
    for i = 1 to UpperBound(email_roles)
     lb_1.additem( email_roles[i] )
    Next
    

Ruby client can use SOAP::WSDLDriverFactory, example can be found at RESTful Web Services.  I kept getting “400 Bad Request” error, looked into the request envelope, it turns out I need to force Ruby running in Unicode mode, to change the KCode for XSD::Charset, run Ruby in ‘-Ku’ switch.

Unfortunately, Google discounted their SOAP search API, it’s hard to run the google search example from RESTful Web Services? Can somebody send me an valid Google SOAP search api key?

Another issue with this SOAP::WSDLDriverFactory, how to control name space in request? Because we added the name space into our service contract.


[ServiceContract(Namespace = "Stakeholder")]
 public interface IOrganizationServiceContract
 {
          [OperationContract]
          OrganizationDto FetchOrganizationById(long id);
 }
Ruby (method not found) Wcf Test Client (Test Passed)
ruby/lib/ruby/1.8/wsdl/operationBinding.rb:40:in `find_operation':
{http://tempuri.org/}FetchOrganizationById not found (RuntimeError)

<s:Header>
 <a:Action s:mustUnderstand="1">Stakeholder/IOrganizationServiceContract/FetchOrganizationById</a:Action>
 <a:MessageID>urn:uuid:60e56fd8-7d46-44db-8b79-61c5e4784a85</a:MessageID>
 <a:ReplyTo>
 <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
 </a:ReplyTo>
 </s:Header>
 <s:Body>
 <FetchOrganizationById xmlns="Stakeholder">
 <id>8172</id>
 </FetchOrganizationById>
 </s:Body>
</s:Envelope>

RESTful service is the way to go, here is a simple demo I learned from how to setup WCF in RESTful service.

Posted in Ruby, SOAP, WPF | Leave a Comment »

PowerUnit changed to NAnt auto-build

Posted by Frank Mao on June 3, 2009

Sourceforge stats shown that PowerUnit has not been updated for 2years, this is wrong! I’m currently still actively playing it. The recent changes including:

  1. Using NAnt auto-build each release. The forth part of version number is subversion revision. The lattest one is 119. The subversion repository is at https://powerunit.svn.sourceforge.net/svnroot/powerunit/
  2. Display PB context version of current PBUnit. Be aware that PB context version must match with the test target. If your target is different, you need to rebuild it, either use NAnt, or in your PB IDE.pbunit_ver
  3. I am using PBScc as my current subversion client, tried PushOK for awhile, it’s OK. Comparing this PBSCC, it’s almost same as old PB dev style.
    PBSCC needs a middle area as the buffer/swap between dev machine to source repository, I think some damon process is monitoring this buffer/swap folder whenver checkin happens, then commit the changes to repo behind the scene. This left the problem of my main src folder shown un-commint-changes icon, doing a diff, the base still no showing the new changes commint through PBSCC, force a update, it said finished a merge, even the src file actually not changed at all.
    pbunit_pbscc_folderpbunit_pbscc_workspace

Posted in PowerUnit, pbunit, powerbuilder | Leave a Comment »