C# WCF 服务引用命名空间与原始命名空间不同
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1200346/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WCF service reference namespace differs from original
提问by Thorarin
I'm having a problem regarding namespaces used by my service references. I have a number of WCF services, say with the namespace MyCompany.Services.MyProduct
(the actual namespaces are longer).
As part of the product, I'm also providing a sample C# .NET website. This web application uses the namespace MyCompany.MyProduct
.
我的服务引用所使用的命名空间有问题。我有许多 WCF 服务,比如命名空间MyCompany.Services.MyProduct
(实际命名空间更长)。
作为产品的一部分,我还提供了一个示例 C# .NET 网站。此 Web 应用程序使用命名空间MyCompany.MyProduct
。
During initial development, the service was added as a project reference to the website and uses directly. I used a factory pattern that returns an object instance that implements MyCompany.Services.MyProduct.IMyService
. So far, so good.
在最初的开发过程中,该服务被添加为网站的项目引用并直接使用。我使用了一个工厂模式,它返回一个实现MyCompany.Services.MyProduct.IMyService
. 到现在为止还挺好。
Now I want to change this to use an actual service reference. After adding the reference and typing MyCompany.Services.MyProduct
in the namespace textbox, it generates classes in the namespace MyCompany.MyProduct.MyCompany.Services.MyProduct. BAD!I don't want to have to change using
directives in several places just because I'm using a proxy class. So I tried prepending the namespace with global::
, but that is not accepted.
现在我想将其更改为使用实际的服务引用。添加引用并MyCompany.Services.MyProduct
在命名空间文本框中键入后,它会在命名空间MyCompany.MyProduct.MyCompany.Services.MyProduct 中生成类。坏的!我不想using
仅仅因为我使用代理类而在几个地方更改指令。所以我尝试在命名空间前面加上global::
,但这不被接受。
Note that I hadn't even deleted the original assembly references yet, and "reuse types" is enabled, but no reusing was done, apparently. However, I don't want to keep the assembly references around in my sample website for it to work anyway.
请注意,我什至还没有删除原始程序集引用,并且启用了“重用类型”,但显然没有重用。但是,我不想在我的示例网站中保留程序集引用,以便它无论如何都能工作。
The only solution I've come up with so far is setting the default namespace for my web application to MyCompany
(because it cannot be empty), and adding the service reference as Services.MyProduct
. Suppose that a customer wants to use my sample website as a starting point, and they change the default namespace to OtherCompany.Whatever
, this will obviously break my workaround.
到目前为止,我想出的唯一解决方案是将我的 Web 应用程序的默认命名空间设置为MyCompany
(因为它不能为空),并将服务引用添加为Services.MyProduct
. 假设客户想要使用我的示例网站作为起点,并且他们将默认命名空间更改为OtherCompany.Whatever
,这显然会破坏我的解决方法。
Is there a good solution to this problem?
这个问题有什么好的解决办法吗?
To summarize: I want to generate a service reference proxy in the original namespace, without referencing the assembly.
总结一下:我想在原始命名空间中生成一个服务引用代理,而不引用程序集。
Note: I have seen this question, but there was no solution provided that is acceptable for my use case.
注意:我已经看到了这个问题,但是没有提供适合我的用例的解决方案。
Edit: As John Saunders suggested, I've submitted some feedback to Microsoft about this:
Feedback item @ Microsoft Connect
编辑:正如约翰桑德斯所建议的,我已经向微软提交了一些关于此的反馈:
反馈项目@Microsoft Connect
采纳答案by Thorarin
I've added a write-up of this solutionto my blog. The same information really, but perhaps a little less fragmented
我已在我的博客中添加了此解决方案的文章。确实是相同的信息,但可能不那么分散
I've found an alternative to using svcutil.exe
to accomplish what I want. It (imo) makes updating the service reference easier than rerunning the utility.
我找到了一种替代方法svcutil.exe
来完成我想要的。它 (imo) 使更新服务引用比重新运行实用程序更容易。
You should explicitly specify a namespace uri on your ServiceContract and DataContracts (see further below for comment).
您应该在 ServiceContract 和 DataContracts 上显式指定命名空间 uri(有关评论,请参见下文)。
[ServiceContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public interface IService
{
[OperationContract]
CompositeType GetData();
}
[DataContract(Namespace = "http://company.com/MyCompany.Services.MyProduct")]
public class CompositeType
{
// Whatever
}
The namespace could be anything, but technically it needs to be a valid uri, so I chose this scheme. You might have to build manually for things to work later, so do that.
命名空间可以是任何东西,但从技术上讲,它需要是一个有效的 uri,所以我选择了这个方案。您可能必须手动构建以便稍后工作,所以这样做。
Once this is done, enable the Show All Filesoption in the Solution Explorer. Expand the service reference you added previously. Double click the Reference.svcmap
file.
完成此操作后,在解决方案资源管理器中启用“显示所有文件”选项。展开您之前添加的服务引用。双击该Reference.svcmap
文件。
There will be a <NamespaceMappings />
element, which you will need to edit. Continuing my example:
将有一个<NamespaceMappings />
元素,您需要对其进行编辑。继续我的例子:
<NamespaceMappings>
<NamespaceMapping
TargetNamespace="http://company.com/MyCompany.Services.MyProduct"
ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>
Save the file, right click the service reference and select Update Service Reference.
保存文件,右键单击服务引用并选择更新服务引用。
You can add as many mappings as you need (I actually needed two). The effect is the same as the svcutil /namespace:
approach, but without having to use the command line util itself, making for easier updating.
您可以根据需要添加任意数量的映射(我实际上需要两个)。效果与svcutil /namespace:
方法相同,但无需使用命令行工具本身,更新更容易。
Difference with svcutil
与 svcutil 的区别
The downside to this approach is that you need to use explicit namespace mappings. Using svcutil
, you have the option to map everything not explicitly mapped like this (the solution John Saunders was referring to):
这种方法的缺点是您需要使用显式命名空间映射。使用svcutil
,您可以选择映射所有未像这样明确映射的内容(John Saunders 所指的解决方案):
svcutil /namespace:*,MyCompany.Services.MyProduct ...
You might think to use:
您可能会考虑使用:
<NamespaceMappings>
<NamespaceMapping
TargetNamespace="*"
ClrNamespace="MyCompany.Services.MyProduct" />
</NamespaceMappings>
but this will notwork, because Visual Studio already implicitly adds this mapping, pointing to the generated namespace name we're trying to get rid of. The above configuration will cause Visual Studio to complain about a duplicate key.
但是这将不会工作,原因是Visual Studio已经隐式添加这种映射,指向我们试图摆脱生成的命名空间名称。上述配置将导致 Visual Studio 抱怨重复键。
Ad explicit namespaces:
When no explit namespace is specified in your code, it seemsthat .NET will generate a uri of the form http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct
. You could map that just as well as the explicit namespaces in my example, but I don't know if there is any guarantee for this behavior. Therefore, going with an explicit namespace might be better.
广告显式命名空间:
当您的代码中未指定显式命名空间时,.NET似乎会生成形式为 的 uri http://schemas.datacontract.org/2004/07/MyCompany.Services.MyProduct
。您可以像我的示例中的显式命名空间一样映射它,但我不知道是否对这种行为有任何保证。因此,使用显式命名空间可能会更好。
NB: mapping two TargetNamespaces to the same ClrNamespace seems to break code generation
注意:将两个 TargetNamespaces 映射到同一个 ClrNamespace 似乎会破坏代码生成
回答by John Saunders
Your use case was wrong.
你的用例是错误的。
You should never have included the service as a reference in the first place.
您一开始就不应该将该服务作为参考。
I believe svcutil.exe will accept a switch specifying the full namespace to use.
我相信 svcutil.exe 将接受指定要使用的完整命名空间的开关。
回答by Sergiu Cosciug
In VS2010 and later versions there is a way to set up custom namespaces. In the solution explorer, select "Show all files" then open "Web references" in the solution tree, select the service, select the Reference.map node, show the properties and set the Custom Tool Namespace property.
在 VS2010 及更高版本中,有一种方法可以设置自定义命名空间。在解决方案资源管理器中,选择“显示所有文件”,然后在解决方案树中打开“Web 引用”,选择服务,选择 Reference.map 节点,显示属性并设置自定义工具命名空间属性。
Unfortunately I don't have enough reputation to show a screenshot.
不幸的是,我没有足够的声誉来显示屏幕截图。