ASMX web service, external WSDLs *without* wsdl.exe - wsdl

I'm working on some legacy code, and I need an asmx to implement a particular wsdl, which is being provided to me.
I would like to receive the root element of the message as either an XmlDocument or XmlNode, rather than the wsdl.exe generated object graph. Is this even possible?

First of all, you should use svcutil.exe, not wsdl.exe, unless you have no other choices.
Second, you don't need either program to implement an external WSDL. Just go write your service so that the XML Serializer will properly serialize and deserialize the incoming message. In particular, if you like processing XML, try this:
[WebMethod]
public XmlElement SomeOperation(XmlElement parameter)
{
}
I believe that the same works with the newer XElement class.
In WCF (which is what you should be using, since Microsoft now considers ASMX web services to be "legacy technology"), I believe you should use the Message type:
[OperationContract]
Message SomeOperation(Message parameter);

Related

How to unit test a method that does automatic deserialization using MVC

I have a method that is declared as so:
public ActionResult Request(Request request)
{
The method is called using JavaScript, but a string is passed in. The deserialization happens automatically.
Now I want to unit test this mimicking what the JavaScript would be passing in, which is a string. How do I unit test using a string instead of Request? When I create my unit test, it expects me to pass in the deserialized type which isn't the end of the world, but it would be nice if I could just copy the string request that gets sent in from the client and test with that.
Is this even possible... to force the automatic deserialization that normally happens?
TrackController c = new TrackController();
c.Request(jsonString);
Deserializing the json into your concrete model object is really the responsibility of the MVC model binder, so I don't think that should be included in the unit test of the controller action.
However I do see some value in testing that you are creating your requests correctly, but I think this is a better fit for an integration test.
You could potentially make http requests to your website directly, which would validate if you're passing correct json to your action.
See more here:
POSTing JSON to URL via WebClient in C#

OpenRasta: Can I use a generic handler for versioning resources gracefully?

We have an OpenRasta service, and we'd like to use media types to version our resources. We'll have a different set of DTOs for each new version, distinguishable by namespace. For each version of the DTOs, we have a corresponding media type.
So DTOs will be mapped to media types like this:
Namespace.Dto.V1.MyResource -> application/vnd.Namespace.Dto.V1.MyResource+json
Namespace.Dto.V2.MyResource -> application/vnd.Namespace.Dto.V2.MyResource+json
The repository implementation will be specific to the version of the DTOs, but the interface is generic. I would like my handler and codec to be generic as well, so I don't need to copy/paste them for each version of the DTOs. So I want my routes to look like this:
ResourceSpace.Has.ResourcesOfType<V1.MyResource>()
.AtUri("MyResource/{resourceID}")
.HandledBy<MyResourceHandler<Dto.V1.MyResource>>()
.TranscodedBy<MyResourceCodec<Dto.V1.MyResource>>()
.ForMediaType(mediaTypeMapper.GetMediaType(typeof(Dto.V1.MyResource)));
//V2 of DTOs
ResourceSpace.Has.ResourcesOfType<V2.MyResource>()
.AtUri("MyResource/{resourceID}")
.HandledBy<MyResourceHandler<Dto.V2.MyResource>>()
.TranscodedBy<MyResourceCodec<Dto.V2.MyResource>>()
.ForMediaType(mediaTypeMapper.GetMediaType(typeof(Dto.V2.MyResource)));
Should this work? Right now, it appears that my service is handling requests with MyResourceHandler<Dto.V1.MyResource> regardless of the Accept header on a GET request, for example.
Any thoughts? We could change our scheme to use URIs like /v1/MyResource/ instead of using the accept header, but it would be great to get this working.
EDIT:
I should add that part of the reason we are using media types for versioning is because this is a service for internal use, not meant to be accessible on the public web.
You're registering two resource types on the same URI, only one will get selected, there's no way to do the distinction at request time.
I don't think versioning in URIs or media types is a good idea on the web. That said, for what you want (different mediatypes), then use the same resource type and use your codec to fill-in the same type from the incoming / outgoing data. That's teh responsibility of a codec in OR, making the junction between a DTO and a media type format.
On incoming requests, we need to know what resource type you want based on the URI. If you have two different types it ought to be different resources. that said if you do the following that'll work too:
ResourceSpace.Has.ResourcesNamed("myResource").AtUri("/myResource").HandledBy<ResourceV1Handler>().And.HandledBy<ResourceV2Handler>();
ResourceSpace.Has.ResourcesOfType<MyV1Resource>().WithoutUri.TranscodedBy<V1Codec>();
ResourceSpace.Has.ResourcesOfType<MyV2Resource>().WithoutUri.TranscodedBy<V2Codec>();
you can then write
public class handler {
public object Post(MyV1Resource resource) {}
public object Post(MyV2Resource resource) {}
}
and that'll work. What you won't be able to do is implement the get in that way, as OR assumes one resource type == one URI in most instances.
As for generics, if you use an IoC container, you can register your handlers in a generic fashion (aka register typeof(IHandler<>) with typeof(Handler<>)). This means any IHandler will get resolved to Handler. You can then simply register HandledBy>() in your registration and you're done. Same applies to codecs (but then again, codecs in OR are there to deal with media type issues, not just as serialization mechanisms, as serialization in itself is evil for the web and should be used seldomly).

Localizing validation messages from Domain Objects (Entities)

It's not my intent to engage in a debate over validation in DDD, where the code belongs, etc. but to focus on one possible approach and how to address localization issues. I have the following behavior (method) on one of my domain objects (entities) which exemplifies the scenario:
public void ClockIn()
{
if (WasTerminated)
{
throw new InvalidOperationException("Cannot clock-in a terminated employee.");
}
ClockedInAt = DateTime.Now;
:
}
As you can see, when the ClockIn method is called, the method checks the state of the object to ensure that the Employee has not been terminated. If the Employee was terminated, we throw an exception consistent with the "don't let your entities enter an invalid state" approach.
My problem is that I need to localize the exception message. This is typically done (in this application) using an application service (ILocalizationService) that is imported using MEF in classes that require access to its methods. However, as with any DI framework, dependencies are only injected/imported if the object was instantiated by the container. This is typically not the case with DDD.
Furthermore, everything I've learned about DDD says that our domain objects should not have dependencies and those concerns should be handled external from the domain object. If that is the case, how can I go about localizing messages such as the one shown above?
This is not a novel requirement as a great many business applications require globalization/localization. I'd appreciate some recommendations how to make this work and still be consistent with the goals of a DDD.
UPDATE
I failed to originally point out that our localization is all database driven, so we do have a Localization Service (via the injectable ILocalizationService interface). Therefore, using the static Resources class Visual Studio provides as part of the project is NOT a viable option.
ANOTHER UPDATE
Perhaps it would move the discussion along to state that the app is a RESTful service app. Therefore, the client could be a simple web browser. As such, I cannot code with any expectation that the caller can perform any kind of localization, code mapping, etc. When an exception occurs (and in this approach, attempting to put the domain object into an invalid state is an exception), an exception is thrown and the appropriate HTTP status code returned along with the exception message which should be localized to the caller's culture (Accept-Language).
Not sure how helpful this response is to you, but localization is really a front-end concern. Localizing exceptions messages as per your example is not common practice, as end users shouldn't see technical details such as those described in exception messages (and whoever will be troubleshooting your exceptions probably has a sufficient level English even if it is not their native language).
Of course if necessary you can always handle exceptions and present a localized, user-friendly message to your users in your front-end. But keeping it as a font-end concern should simplify your architecture.
As Clafou said, you shouldn't use exceptions for passing messages to the UI in any way.
If you still insist in doing this, one option is to throw an error code instead of the message
throw new InvalidOperationException("ERROR_TERMINATED_EMPLOYEE_CLOCKIN");
and then, when it happens, do whatever you need to do with the exception (log, look up localization, whatever).
If localisation is important part of the domain/application you should make it a first class citizen and inject wherever it belongs. I am not sure what you mean with "DDD says that our domain objects should not have dependencies" - please explain.
You are correct for trying to avoid adding internal dependencies to your domain model objects.
A better solution would be to handle the action inside of a service method such as:
public class EmployeeServiceImpl implements EmployeeService {
public void ClockEmployeeIn(Employee employee) throws InvalidOperationException {
if (employee.isTerminated()) {
// Localize using a resource lookup code..
throw new InvalidOperationException("Error_Clockin_Employee_Terminated");
}
employee.setClockedInAt(DateTime.Now);
}
}
You can then inject the service using your DI framework at the point where you will be making the clockin call and use the service to insulate your domain objects from changes to business logic.

WCF Client calling a Java Web Service : XmlSerializer cannot find Derived types

This seems like a fundamental Web Services problem. However an elegant solution is elusive based on some research I have been able to do. I guess I am missing something here
I am using a WCF client to connect to a External web service of which I have no control. The external WS is java based. There are a bunch of assemblies which are provided to call the methods in web service. These assemblies have base classes and derived classes. The web service methods can take Base class as param whereas from the WCF Client I instantiate a Derived class and pass it to the method.
To simulate this scenario, I created a small project with one ClassLibrary which has a BaseClass and a DerivedClass with one method.
Then I create an asmx web service and add a HelloWorld method inside it. I add a reference to the ClassLibrary. This method takes a BaseClass type param.
Then I create a Service Reference to the ASMX web service. In the proxy class, I add a XmlSerializerFormatAttribute to the method if it is already not there.
From the WCF client, I call the ASMX web method
BaseClass bc = new Derived();
ServiceReference1.TestService ts = new WCFTest.ServiceReference1.TestService();
lbl1.Text = (c1.HelloWorld(bc));
The call fails with error
The type ClassLib.Derived was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
The only way I could call this web service method was by adding XmlInclude attribute to the BaseClass in the ClassLibrary.
In my scenario, this library is a dll provided by an external vendor. I cannot add attributes to its classes. I have looked a DataContractSerializer and KnownTypes and XmlSerializer ctor. However those solutions do not seem to be applicable in my scenario.
How can I make XMLSerializer see the Derived classes in the assemblies I have referencing in the WCF Client? Is there an elegant solution?
Thanks,
Hem
Including your own type mapping for an XmlSerializerOperationBehavior may just work, but I haven't tried this (see GetXmlMappings).
http://msdn.microsoft.com/en-us/library/system.servicemodel.description.xmlserializeroperationbehavior.aspx
Alternatively, forcing use of the DataContractSerializer via a DataContractSerializerOperationBehavior (as opposed to the XmlSerializerOperationBehavior it's using now) may work too, if you specify your own known types
http://msdn.microsoft.com/en-us/library/ms576751%28v=vs.85%29.aspx
Finally, as a last resort, you can force use of the DataContractSerializer using the DataContractSerializerOperationBehavior, then specify your own DataContractSurrogate to force use of the XmlSerializer where you can pass custom types to its constructor (which circumvents the requirement for the XmlInclude attribute).
http://msdn.microsoft.com/en-us/library/ms751540.aspx
Hope that helps.

WSDL importer generates faulty server

I've been trying to get a soap server up that implements (is that the correct term?) a wsdl specification made by a third party. I have used Delphi's wsdl importer. (Part of) the generated code looks like this:
miniPortType = interface(IInvokable)
['{824D172A-9C1F-D202-5B21-4C324553BCF0}']
// Cannot unwrap:
// - Input element wrapper name does not match operation's name
function miniService(const aMessage: MiniMessageType): MiniAnswerType; stdcall;
end;
When called, the server says that "No method named 'MiniMessageType' is supported by interface 'miniPortType'".
I can only get this to work by making the name of the function and name of the main element of the message the same.
I think it should be possible to have different names. At least soapUI doesn't complain. And I actually have no choice but to implement the wsdl as is. Does anybody know how I can work around this?
I'm using Delphi 2007.
Thanks, Miel.
If I recall correctly, the SOAP interface is actually defined in a "table" at the bottom of the definitions, and it is this which is used to do the conversion between Delphi types and SOAP types in the communications. I've "corrected" this sort of thing in the past by manually changing the table building calls, but you have to be careful, and may also need to mangle the SOAP text at the appropriate point to make it all fit.

Resources