Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.9.9.3 change of datacontract namespace not working? #195

Closed
mronnblom opened this issue Feb 12, 2019 · 17 comments · Fixed by #242
Closed

0.9.9.3 change of datacontract namespace not working? #195

mronnblom opened this issue Feb 12, 2019 · 17 comments · Fixed by #242
Labels

Comments

@mronnblom
Copy link

Hi!

The way datacontract namespaces are generated in metadata have changed in 0.9.9.3 (or maybe 0.9.9.2). With 0.9.9.1, datamembers got the same namespace as the service. See this example request generated by SoapUI for my service:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://mynamespace.com/services/foo/v1/">
   <soapenv:Header/>
   <soapenv:Body>
      <v1:GetPerson>
         <v1:request>
            <v1:IdentificationNumber>123</v1:IdentificationNumber>
         </v1:request>
      </v1:GetPerson>
   </soapenv:Body>
</soapenv:Envelope>

But with 0.9.9.3 (and also latest in master), the datamembers get a separate namespace:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://mynamespace.com/services/foo/v1/" xmlns:mim="http://schemas.datacontract.org/2004/07/Foo.Soap.V1">
   <soapenv:Header/>
   <soapenv:Body>
      <v1:GetPerson>
         <v1:request>
            <mim:IdentificationNumber>123</mim:IdentificationNumber>
         </v1:request>
      </v1:GetPerson>
   </soapenv:Body>
</soapenv:Envelope>

This is all well and good for the WSDL itself, since this is the way that WCF in .Net Framework generates namespaces. However, SoapCores runtime code can't seem to recognize the parameters (in the example above "IdentificationNumber"). I have tried changing the order of the parameters, and having an explicit namespace on the datacontract, but that is not used. No matter what I do, parameters are null when receiving a request in my service.

@kotovaleksandr
Copy link
Member

Hi @MathiasRonnblom !
My service:

[ServiceContract(Namespace = "http://mynamespace.com/services/foo/v1/")]
public interface ISampleService
{
	[OperationContract]
	void GetPerson(Request request);
}

public class Request
{
	public int IdentificationNumber { get; set; }
}

SoapUI request:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://mynamespace.com/services/foo/v1/" xmlns:mod="http://schemas.datacontract.org/2004/07/Models">
   <soapenv:Header/>
   <soapenv:Body>
      <v1:GetPerson>
         <!--Optional:-->
         <v1:request>
            <!--Optional:-->
            <mod:IdentificationNumber>222</mod:IdentificationNumber>
         </v1:request>
      </v1:GetPerson>
   </soapenv:Body>
</soapenv:Envelope>

Yes, namespace of member changed, but SoapCore resolve member value correctly:
image
Whats difference in my code and yours? Can you attach full example? I should reproduce this issue with debugger.

@mronnblom
Copy link
Author

Yes, your example indeed works! I had to drill deeper, and found two scenarios where the parameter value isn't picked up.

Try this code:

[ServiceContract(Namespace = "http://mynamespace.com/services/foo/v1/")]
public interface ISampleService
{
	[OperationContract]
	void GetPerson(Request request);

	[OperationContract]
	void GetPerson2(RequestNotWorking request);

	[OperationContract]
	void GetPerson3(RequestNotWorking2 request);
}

namespace SoapCoreTestService
{
	public class Request
	{
		public string IdentificationNumber { get; set; }
	}
}

// This request doesn't work since its namespace contains a dot (took me a while to find!)
namespace SoapCoreTestService.Requests 
{
	public class RequestNotWorking
	{
		public string IdentificationNumber { get; set; }
	}
}

// This request doesn't work since it has DataContract-attribute
using System.Runtime.Serialization;
namespace SoapCoreTestService
{
	[DataContract]
	public class RequestNotWorking2
	{
		public string IdentificationNumber { get; set; }
	}
}

kotovaleksandr pushed a commit to kotovaleksandr/SoapCore that referenced this issue Feb 25, 2019
@kotovaleksandr
Copy link
Member

@MathiasRonnblom Check on latest master branch, should be work good.

@kotovaleksandr
Copy link
Member

@MathiasRonnblom I forget to tell you: if you mark class as "DataContract" your should add "DataMember" for properties which you want send\receive to client (sample RequestNotWorking2).

@mronnblom
Copy link
Author

@kotovaleksandr Thanks, all the requests work now! Unfortunately, it seems to have broken nested ComplexTypes.. Try this example:

[ServiceContract(Namespace = "http://mynamespace.com/services/foo/v1/")]
public interface ISampleService
{
	[OperationContract]
	DTO.Person GetPerson();
}

public DTO.Person GetPerson()
{
	return new DTO.Person
	{
		Address = new DTO.Address
		{
			Street = "foo"
		}
	};
}

namespace SoapCoreTestService.DTO
{
	[DataContract]
	public class Person
	{
		[DataMember]
		public Address Address { get; set; }
	}
}

namespace SoapCoreTestService.DTO
{
	[DataContract]
	public class Address
	{
		[DataMember]
		public string Street { get; set; }
	}
}

Error message when adding the WSDL in SoapUI:
Source: https://localhost:44354/SampleService.svc Error: type 'Address@http://schemas.datacontract.org/2004/07/SoapCoreTestService.DTO' not found.

Seems that "Address" is missing from the generated WSDL.

@kotovaleksandr kotovaleksandr reopened this Mar 5, 2019
kotovaleksandr pushed a commit to kotovaleksandr/SoapCore that referenced this issue Mar 5, 2019
@kotovaleksandr
Copy link
Member

Check on my fork:
https://github.com/kotovaleksandr/SoapCore

@mronnblom
Copy link
Author

@kotovaleksandr I get a similar error with that fork, when adding the WSDL to SoapUI. I have created a new private Github repo with a stripped down version of my code, and given you access. That way you can try it yourself.

@mronnblom
Copy link
Author

I forgot to say that the current code in that repo references the 0.9.9.1 Nuget package, and works with that. However, it doesn't work with 0.9.9.3, the code from DigDes/master or kotovaleksandr/SoapCore.

kotovaleksandr pushed a commit to kotovaleksandr/SoapCore that referenced this issue Mar 6, 2019
@kotovaleksandr
Copy link
Member

I'm sorry, check on my fork again. On your repo works fine.

@mronnblom
Copy link
Author

@kotovaleksandr It works now! Thanks for your quick work! :)

Are there plans for merging this to the DigDes repo, and make a new Nuget package?

@kotovaleksandr
Copy link
Member

https://www.nuget.org/packages/SoapCore/0.9.9.4

@kotovaleksandr
Copy link
Member

@MathiasRonnblom Hi, i check again your model with latest SoapCore and i observe: WSDL generated with incorrect namespaces and WSDL generation not check Order property on DataMember attribute.
Can you check WSDL generation and method calling with your project on my fork https://github.com/kotovaleksandr/SoapCore ?

@mronnblom
Copy link
Author

@kotovaleksandr I finally had time to check your fork, and it works nicely with custom DataContract namespace, as well as Order attributes on DataMember. I.e. this request works (PersonId comes before IdentificationNumber, and both get populated in runtime):

	[DataContract(Namespace = Constants.Namespace)]
	public class GetPersonRequest
	{
		[DataMember(Order = 1)]
		public string PersonId { get; set; }

		[DataMember(Order = 2)]
		public string IdentificationNumber { get; set; }
	}

Also, I see that you have fixed the null check on baseType in MetaWCFBodyWriter/HasBaseType! 👍

However, it seems that it does no longer work with default DataContract namespace, so this request gives me an error when adding the service to SoapUI:

	[DataContract]
	public class GetPersonRequest
	{
		[DataMember(Order = 1)]
		public string PersonId { get; set; }

		[DataMember(Order = 2)]
		public string IdentificationNumber { get; set; }
	}

This is the error from SoapUI:

Error: Could not find type 'GetPersonRequest@http://mynamespace/v1/'.
Do you mean to refer to the element named 
GetPersonRequest@http://schemas.datacontract.org/2004/07/NyNamespace.Soap.V1.DTO.Request
(in MyService.svc)?

kotovaleksandr pushed a commit to kotovaleksandr/SoapCore that referenced this issue Mar 22, 2019
@bhenden
Copy link
Contributor

bhenden commented May 25, 2019

if (dataContractAttribute != null && dataContractAttribute.IsNamespaceSetExplicitly)

We have some complex types with namespace explicitly set to an empty string. This line breaks our code as the type end up in the wrong namespace. Correct namespace in our code would be "contract.Namespace". I fixed our code by adding

&& !string.IsNullOrEmpty(dataContractAttribute.Namespace)

but I don't know the code well enough to say this doesn't break other things?

@kotovaleksandr
Copy link
Member

@bhenden send PR with this fix to develop branch, i see it late. i think this change doesn't break any existence service.

@github-actions
Copy link

This issue is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale label Jul 27, 2021
@github-actions
Copy link

This issue was closed because it has been inactive for 14 days since being marked as stale.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants