what is IsWrapped Attribute in WCF class - wcf

/// <summary>
/// Service Contract Class - GetItemResponse
/// </summary>
[MessageContract(IsWrapped = true)]
public partial class GeItemResponse
{
}
In the above IsWrapped attribute is set as true , what is the use of this attribute , could anyone explain it?

When you set IsWrapped to false, the message body won't be wrapped in an element with the action name.
here you can read more: What is the purpose of the IsWrapped property in WCF

Related

Akka.net Hyperion IgnoringDataMember

I use akka.net in a cluster schema. (n) processing nodes, with currently 1 lighthouse.
One of the package that navigate throught network expose langage information.
/// <summary>
/// Define scored a suite of token info
/// </summary>
/// <seealso cref="Hammer.Immutable.ImmutableObject" />
[DataContract]
public sealed class TokenSuite : ImmutableObject, IIdItem
{
#region Ctor
/// <summary>
/// Initializes a new instance of the <see cref="TokenSuite"/> class.
/// </summary>
public TokenSuite(Guid id, string langCode)
: base(id, langCode)
{
this.Id = id;
this.LangCode = langCode;
if (!string.IsNullOrEmpty(langCode))
LangInfo = CultureInfo.GetCultureInfoByIetfLanguageTag(langCode);
}
#endregion
#region Properties
/// <summary>
/// Gets the identifier.
/// </summary>
[DataMember]
public Guid Id { get; }
/// <summary>
/// Gets the main language code.
/// </summary>
[DataMember]
public string LangCode { get; }
/// <summary>
/// Gets the lang information.
/// </summary>
[IgnoreDataMember]
public CultureInfo LangInfo { get; }
#endregion
In local no problem but when it pass through the network (serialized) i got this issue on the lighthouse :
Reading the error it seems coming from the CultureInfo Object but it is flag to be ignored in the serializations.
I use Akka version 1.3.5, Hyperion 0.9.8, Akka.Serialization.Hyperion 1.3.2-beta54.
I try to serialize locally and it works :
var serializer = Context.System.Serialization.FindSerializerForType(typeof(TokenSuite));
var data = serializer.ToBinary(result);
var rtoObjectBack = serializer.FromBinary<TokenSuite>(data);
Any idea ?
Hyperion does not make any use of data contract attributes. This also means that [IgnoreDataMember] won't be taken into account.
Probably it fails when trying to deserialize a CultureInfo object, you've provided. You can always try to convert that to string, and resolve after deserialization.

Modify the HttpContent response in the Web API pipeline

I would like wrap my web api controller response in a generic class and can't work out how to get the actual type from HttpResponseMessage.Content.
e.g. My Controller
[ResponseType(typeof(ApiAuthentication))]
public IHttpActionResult PostLogOnTest()
{
ApiAuthentication loginResponse = new ApiAuthentication();
return Ok(loginResponse);
}
I need to be able to wrap all the controller response in a 'data' container. I could code this response class into each method but I thought it would be nice to do in common place? So I have a class
[DataContract]
public class ApiResponse<T>
{
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>
/// The data.
/// </value>
[DataMember(Name="data")]
public T Data { get; set; }
}
I can hook into a MessageHandler and get the HttpResponseMessage but when I try to get the Content from .Content - it comes as a ObjectContent<> - i just want the ApiAuthentication so i can then create new HttpResponseMessage>
Is there any way to do this or easier way?
Thanks

Silverlight is not liking my WCF MessageContract. Why?

I am attempting to upload a file through a Silverlight client using the following MessageContract:
[MessageContract]
public class CategoryClientFileTransferMC : IDisposable
{
/// <summary>
/// CategoryID - Category identity.
/// </summary>
[MessageHeader(MustUnderstand = true)]
public int CategoryID;
/// <summary>
/// ID - File identifier.
/// </summary>
[MessageHeader(MustUnderstand = true)]
public string ID;
/// <summary>
/// Length - File length in bytes.
/// </summary>
[MessageHeader(MustUnderstand = true)]
public long Length;
/// <summary>
/// FileByteStream - File stream.
/// </summary>
[MessageBodyMember(Order = 1)]
public Stream FileByteStream;
/// <summary>
/// Dispose the contract.
/// </summary>
public void Dispose()
{
if (FileByteStream != null)
{
FileByteStream.Close();
FileByteStream = null;
}
}
}
My problem is that the generated operation method on the client only takes a single argument; a byte array called FileByteStream. In other (non-Silverlight) clients I've created it asks for the MemberHeader fields as well. Without specifying these headers, the server has no idea what to do with the file. How can I set these headers when I call the operation?
Also, is there a better way to upload a file from a Silverlight client? This has been a huge headache.
Thanks.
The Silverlight subset of the WCF client does not support the [MessageHeader] attribute. You can still set message headers, but it's not as straightforward as in other platforms. Basically, you'll need to set the headers using the operation context, prior to making the call, like in the example below:
var client = new SilverlightReference1.MyClient();
using (new OperationContextScope(client.InnerChannel))
{
string contractNamespace = "http://tempuri.org/";
OperationContext.Current.OutgoingMessageHeaders.Add(
MessageHeader.CreateHeader("CategoryId", contractNamespace, 1));
OperationContext.Current.OutgoingMessageHeaders.Add(
MessageHeader.CreateHeader("ID", contractNamespace, "abc123"));
OperationContext.Current.OutgoingMessageHeaders.Add(
MessageHeader.CreateHeader("Length", contractNamespace, 123456L));
client.UploadFile(myFileContents);
}
Where contractNamespace is the XML namespace for the message header fields (IIRC they default to the same as the service contract). You can use Fiddler and something like the WCF Test Client to see which namespace is used there.

Problem with DataContract and hierarchy on WCF

i have a problem with an object in my wcf project.
I have lets say this object:
[DataContract(Name="ClassA")]
public class Person{
//---attributes---
}
[DataContract(Name="ClassB")]
public class Men : Person{
//---attributes---
}
Where ClassB is child of ClassA on the other side.
Then i have a method that is post:
[OperationContract]
[WebInvoke(UriTemplate= "Person", ResponseFormat = WebMessageFormat.Json, Method= "POST")]
public string PostPerson(Person person) {
if(person is Men){
//code...
}
}
The thing is that i receive the person (in the other side, they sendme as a ClassB) but the person is Men returns false.. why?
You need to add the [ServiceKnownType(typeof(Men))] attribute to the PostPerson method.
As Ryan Gross mentions, you need Men to be a known type. Here's a similar question/answer here on SO. One option not mentioned in the linked article is the KnownType attribute. Here's an example of code I've used in the past. The prerequisite is that this class is the base class for all of your data contracts and all of your data contracts are in the same assembly:
/// <summary>
/// Base class for all data contracts.
/// </summary>
[DataContract(Name = "Base", Namespace = "your namespace")]
[KnownType("GetKnownTypes")]
public class BaseDC : IExtensibleDataObject
{
#region Constants and Fields
/// <summary>
/// Instance used to control access to the known types list.
/// </summary>
private static readonly object _knownTypesLock = new object();
/// <summary>
/// Classes derived from this class. Needed to ensure proper functioning of the WCF data
/// constract serializer.
/// </summary>
private static List<Type> _knownTypes;
#endregion
#region Properties
/// <summary>
/// Gets or sets an <c>ExtensionDataObject</c> that contains data that is not recognized as belonging to the
/// data contract.
/// </summary>
public ExtensionDataObject ExtensionData { get; set; }
#endregion
#region Public Methods
/// <summary>
/// Enumerates the types in the assembly containing <c>BaseDC</c> that derive from <c>BaseDC</c>.
/// </summary>
/// <returns>List of <c>BaseDC</c>-derived types.</returns>
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
Justification = "Not appropriate for a property.")]
public static IEnumerable<Type> GetKnownTypes()
{
lock (_knownTypesLock)
{
if (_knownTypes == null)
{
_knownTypes = new List<Type>();
Assembly contractsAssembly = Assembly.GetAssembly(typeof(BaseDC));
Type[] assemblyTypes = contractsAssembly.GetTypes();
foreach (Type assemblyType in assemblyTypes)
{
if (assemblyType.IsClass && !assemblyType.IsGenericType)
{
if (assemblyType.IsSubclassOf(typeof(BaseDC)))
{
_knownTypes.Add(assemblyType);
}
}
}
_knownTypes.Add(typeof(BaseDC));
}
return _knownTypes;
}
}
#endregion
}

WCF Message Contract namespace issue

I have following MessageContract
[MessageContract(IsWrapped = true, WrapperName = AuthorizationXmlElementNames.ElementNames.GetUserRightsResponse,
WrapperNamespace = AuthorizationXmlElementNames.Namespace)]
public class GetUserRightsResponseMessage
{
#region Properties
/// <summary>
/// Gets or sets GetUserRightsResponse.
/// </summary>
[MessageBodyMember(Namespace = AuthorizationXmlElementNames.Namespace)]
public GetUserRightsResponse GetUserRightsResponse { get; set; }
/// <summary>
/// Gets or sets ResponseHeader.
/// </summary>
[MessageHeader(
Name = XmlCoreElementNames.ElementNames.ResponseHeader,
Namespace = XmlCoreElementNames.Namespace,
ProtectionLevel = ProtectionLevel.None)]
public ResponseHeader ResponseHeader { get; set; }
#endregion
}
GetUserRightsResponse class looks like this
[XmlRoot(ElementName = AuthorizationXmlElementNames.ElementNames.GetUserRightsResponse,
Namespace = AuthorizationXmlElementNames.Namespace, IsNullable = false)]
[Serializable]
//[MessageContract(WrapperName = AuthorizationXmlElementNames.ElementNames.GetUserRightsResponse, WrapperNamespace = AuthorizationXmlElementNames.Namespace)]
public class GetUserRightsResponse
{
#region Constructors and Destructors
/// <summary>
/// Initializes a new instance of the <see cref="GetUserRightsResponse"/> class.
/// Initialize a new instance of the <see cref="GetUserRightsResponse"/> class.
/// </summary>
public GetUserRightsResponse()
{
this.UserServiceAccesses = new UserServiceAccesses();
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the user rights for the current user.
/// </summary>
//[MessageBodyMember(Namespace = AuthorizationXmlElementNames.Namespace)]
public UserServiceAccesses UserServiceAccesses { get; set; }
#endregion
}
XmlCoreElementNames.Namespace is the constant string for namespace and it's value is urn:MyNamespace:Authorization
I return an instance of the GetUserRightsResponseMessage from my operation contract. But I always get wrong namespace for the GetUserRightsResponse instance contained in the returned object. The returned XML part looks like the following.
<s:Body u:Id="_0">
<GetUserRightsResponse xmlns="urn:MyNamespace:Authorization">
<GetUserRightsResponse i:nil="true"
xmlns:a="http://schemas.datacontract.org/2004/07/MyMessageContract.MessageContracts"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />
</GetUserRightsResponse>
</s:Body>
Why do i always get the namespace xmlns:a="http://schemas.datacontract.org/2004/07 for the property in the returned object? What does xmlns:a mean?
Both GetUserRightsResponse elements are in namespace "urn:MyNamespace:Authorization", because the default namespace declaration on the outer one is inherited by the inner one.
xmlns:a="http://schemas.datacontract.org/2004/07/MyMessageContract.MessageContracts" is a namespace declaration which defines a namespace prefix ("a") which isn't actually used in your message. So it has no effect at all on the meaning of the XML message and could be omitted. Its presence is a quirk of the Microsoft implementation, perhaps triggered by the naming collision between your message wrapper element name and the data contract name (but I'm just guessing about this).
If your clients are fully XML compliant, this shouldn't be a problem for you at all. However, there are some non-compliant SOAP client toolsets around which are fussy about the treatment of namespace declarations. If you are very unlucky you might find you have one which is confused by an unused namespace prefix declaration.
You are not getting wrong namespace, as far as I can see.
All elements are set to "urn:MyNamespace:Authorization" which I imagine is the AuthorizationXmlElementNames.Namespace.
xmlns:a="http://schemas.datacontract.org/2004/07/MyMessageContract.MessageContracts" points to Microsoft's schema for message contracts. Now this does not seem to have been used in the snippet you published, so I am surprised it is there at all but this is an innocent namespace since you do not have any element or attribute in that namespace.