REST-based service - handling empty strings - wcf

I have developed a REST-based web service. This service takes four parameters. The last two of these parameters may be empty strings. My question is, what is the recommended approach for dealing with empty strings?
Thanks!

You have two options here - either define the parameters in the UriTemplate of the operation as query variables (and not path variables), or if this is not a GET operation, you can let the operation body receive them.
Case 1:
[WebGet(UriTemplate="/GetData?x={x}&y={y}&z={optional1}&w={optional2}")]
string GetData(int x, int y, string optional1, string optional2);
Case 2:
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string DoSomething(int x, int y, string optional1, string optional2);

Related

Can I change a WCF method parameter from int data type to long?

Let's say I have an existing method in a WCF service:
[OperationContract]
CustomerInfo GetCustomerInfo(int customerId);
It turns out I need to change this to take a long as its parameter instead of an int. Would that break existing clients? Or is there some implicit conversion that happens?

Locating the parameter of an Operation in System.ServiceModel.Channels.Message in WCF

Suppose we have the following Service contract:
[ServiceContract]
public interface IPing
{
[OperationContract]
string Ping(string parameter1, string parameter2);
}
I'm wondering, how it would be possible to find a particular parameter value, say the value of parameter1 for example, in the System.ServiceModel.Channels.Message created server side.
Thanks!
It's the task of the IDispatchMessageFormatter to convert between the operation parameters and the Message object. Usually the message is created with a XML body, and the parameters are XML elements, but that's just one possible implementation (it's perfectly valid for a formatter to completely disregard the message and assign whatever values it sees fit for the operation parameters).
You can learn more about message formatters in the blog post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/03/wcf-extensibility-message-formatters.aspx.

In WCF can I have a wildcard character in a literal segment of my UriTemplate?

I am authoring a RESTful WCF service using .Net 4.0. I want the following two URLS:
/root/document/{ids}?fields={fields}
/root/externaldocument/{ids}?fields={fields}
to map to the same interface member:
Documents GetDocuments(string ids, string fields)
I have tried putting a wildcard into a literal URL segment:
[OperationContract]
[WebGet(UriTemplate = "/root/*document/{ids}?fields={fields}")]
Documents GetDocuments(string ids, string fields)
However, this is not valid and I get the following exception:
The UriTemplate '/root/*document/{ids}?fields={fields}' is not valid; the
wildcard ('*') cannot appear in a variable name or literal... Note that a
wildcard segment, either a literal or a variable, is valid only as the last
path segment in the template
If I wrap the wildcard segment in a template brace:
[OperationContract]
[WebGet(UriTemplate = "/root/{*document}/{ids}?fields={fields}")]
Documents GetDocuments(string ids, string fields)
Then I get an exception because there is no such input parameter in the method arguments:
Operation 'GetDocuments' in contract 'IAPIv2' has a UriTemplate that expects a
parameter named 'DOCUMENTS', but there is no input parameter with that name
on the operation.
My workaround is simply to have two entries, pointing to different methods, and then have the methods call a common implementation:
[OperationContract]
[WebGet(UriTemplate = "/root/document/{ids}?fields={fields}")]
Documents GetDocuments(string ids, string fields)
[OperationContract]
[WebGet(UriTemplate = "/root/externaldocument/{ids}?fields={fields}")]
Documents GetExternalDocuments(string ids, string fields)
But this seems kind of ugly.
I have read the documentation and cannot find this point specifically address. Is there any way I can have a wildcard literal segment in WCF? Or is this not possible in WCF?
As it turned out, the two entry points needed to have slightly different functionality. So I needed to capture which URL was used to enter the method. What I ended up doing was the following:
[OperationContract]
[WebGet(UriTemplate = "/root/{source}ocuments/{ids}?fields={fields}")]
DocumentCollection GetDocumentsById(string source, string ids, string fields);
Both URLs:
/root/document/{ids}?fields={fields}
/root/externaldocument/{ids}?fields={fields}
map to the same URL template, and thus I needed to have only a single entry with a single UriTemplate in my interface.
The "source" input parameter captures either "d" if the second segment is "documents or "externald" if the second segment is "externaldocuments". Thus by inspecting this input parameter, the method can react appropriately, depending upon which URL was used to reach the method.
Note that I could not use the following for the UriTemplate:
[WebGet(UriTemplate = "/root/{source}documents/{ids}?fields={fields}")]
because in this case, the incoming URL
/root/document/{ids}?fields={fields}
would not match the template, even though the template matches if an empty string ("") is used for the source input parameter. Apparently the UriTemplate matching algorithm requires there to be at least one character in a parameter capturing group for there to be a match.

How to define a set of input parameters in Pex?

Say I have MyClass with 100s of fields.
If I use an object of MyClass as an input param, Pex would simply choke trying to generate all possible combinations (mine runs into 1000s of paths even on a simple test)
[PexMethod]
void MytestMethod(MyClass param){...}
How can I tell Pex to use only a set of predefined objects of MyClass rather than having it trying to be smart and generate all possible combinations to test?
In other words I want to manually specify a list of possible states for param in the code above and tell Pex to use it
Cheers
If you find that Pex is generating large amounts of irrelevant, redundant, or otherwise unhelpful inputs, you can shape the values that it generates for your parametrized unit tests' input using PexAssume, which will ensure that all generated inputs meet a set of criteria that you provide.
If you were wanting to ensure that arguments came from a predefined collection of values, for instance, you could do something like this:
public void TestSomething(Object a) {
PexAssume.IsTrue(someCollection.Contains(a));
}
PexAssume has other helper methods as well for more general input pruning, such as IsNotNull, AreNotEqual, etc. What little documentation is out there suggests that there is some collection-specific functionality as well, though if those methods exist, I'm not familiar with them.
Check out the Pex manual for a bit more information.
Pex will not try to generate every possible combination of values. Instead, it analyses your code and tries to cover every branch. So if you have
if (MyObject.Property1 == "something")
{
...
}
then it will try to create an object that has Property1 == "something". So limiting the tests to some predefined objects is rather against the 'Pex philosophy'. That said, you may find the following information interesting.
You can provide a Pex factory class. See, for instance, this blog post or this one.
[PexFactoryClass]
public partial class EmployeeFactory
{
[PexFactoryMethod(typeof(Employee))]
public static Employee Create(
int i0,
string s0,
string s1,
DateTime dt0,
DateTime dt1,
uint ui0,
Contract c0
)
{
Employee e0 = new Employee();
e0.EmployeeID = i0;
e0.FirstName = s0;
e0.LastName = s1;
e0.BirthDate = dt0;
e0.StartDateContract = dt1;
e0.Salary = ui0;
e0.TypeContract = c0;
return e0;
}
}
Pex will then call this factory class (instead of a default factory) using appropriate values it discovers from exploring your code. The factory method allows you to limit the possible parameters and values.
You can also use PexArguments attribute to suggest values, but this will not prevent Pex from trying to generate other values to cover any branches in your code. It just tries the ones you provide first.
[PexArguments(1, "foo")] // try this first
void MyTest(int i, string s)
{
...
}
See here for more information on PexArguments and also search for 'seed values' in the PDF documentation on Parameterized Test Patterns.

Do I need to translate enum values across a WCF service?

The scenario is as follows: I implemented a WCF service (lets call it X) which has its own data objects.
The service X is using another WCF service (Y) which has its own set of data objects. Service X needs to pass some data it receive from service Y to its clients (service X clients).
As far as i know, it is considered a "best practice" to translatethe objects received from Y service to data objects of X service.
What is the best practice when it comes to Enum values? Do i need to map each enum value or is there another way?
Generally the idea is to isolate users of your service from changes in your implementation. Therefore, you do not expose your implementation types on the wire. Image the situation where you decide to rename an enum value. If the service consumer does not update their implementation you will have introduced a breaking change as the service user will be sending the old enum value to you which will not deserialize correctly.
In addition you may find that not all of the enum values are applicable to users of your service (maybe they are used internally)
So, yes, you should translate enum values just like other types
If you give your enums explicit numeric values you could translate between them using casts
class Program
{
static void Main(string[] args)
{
Internal i = Internal.Too;
External e = (External) i;
Console.WriteLine(e);
}
}
enum Internal
{
One = 1,
Too = 2
}
[DataContract]
enum External
{
[EnumMember]
One = 1,
[EnumMember]
Two = 2
}
However, you would have to be careful that they did not become out of sync