How to catch missing required fields without crashing?

May 31, 2013 at 9:26 PM
Markus,

Today I had a problem. I made a call and got an error in ServiceTestHarnessUI (around line 196) - but the error message didn't give me any clue as to the problem.

Even when stepping through the code in the host, the method seemed to work just fine - until I hit the return statement.

The problem turned out to be that, in the contract, I had some fields with:
[DataMember(IsRequired = true)]

And I was sending up data with empty strings. This resulted in the following error message:

Exception has been thrown by the target of an invocation
or
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

For us folks not used to all this service layer stuff nor the magic in the FW that makes it all work so well - those messages don't help too much. But if the message was something like "required values not supplied" - most of us could figure out what to do.

The problem is that, since the setting is declarative instead of imperative and I have no idea where I would put code to get the declarative value/restriction and compare that to the request object.

I am sure this is something simple like "Oh, just add a XXX event handler to the ZZZ class and just check for YYY". So was wondering if you could help with the XXX, YYY, and ZZZ so I can write the code... :)

Thanks,

Fletcher
Coordinator
Jun 2, 2013 at 9:46 PM
Yeah, I wish this was a bit more intuitive as this has bit me a few times too. But I am not sure I can do a whole lot about it without being detrimental to performance. Basically what is happening here is that WCF is handing contracts around and they do not match and thus you are getting a WCF pipeline error. It's really not part of our framework, which is why I can't do much about it.

Of course the question is "why is the required field not there". Let's say we have a data contract like this:
[DataContract]
public class MyContract
{
    [DataMember(IsRequired=true)]
    public string FirstName { get; set; }
}
The trouble is that it should be initialized to null, otherwise the system complains. We make it a habit to always do this to avoid the problem:
[DataContract]
public class MyContract
{
    public MyContract()
    {
        FirstName = string.Empty;
    }

    [DataMember(IsRequired=true)]
    public string FirstName { get; set; }
}
So that fixes the issue, but it is a hassle and not something I like. In the test harness, we will highlight a field in red if it is null, but I am not sure what else to do.

One of the things we often throw around is that we would like to create a better language to define contracts. Using classes is really a hack, if you ask me. Something like this would be cool:
DataContract MyContract
{
    string FirstName;
    string LastName;
    optional string MiddleName;
}
And then process that during compilation and turn it into a C# class that does all the right things. This would eliminate a lot of stupid problems one can have in contracts. So I def. have this on my list. But then people want all this other stuff, like new themes and error providers, and ... :-)


Markus