后端 - 一问三不知 https://www.sapze.com Wed, 15 Feb 2023 03:14:34 +0000 zh-CN hourly 1 https://wordpress.org/?v=4.9.22 后端 - 一问三不知 https://www.sapze.com/wcf-net-core-trace-log-and-credential.html Wed, 28 Dec 2022 15:37:46 +0000 https://www.sapze.com/?p=210 阅读全文 ]]> 日志记录

旧代码:

    public class TraceExtension : SoapExtension
    {
        Stream _oldStream;
        Stream _newStream;

        public override Stream ChainStream(Stream stream)
        {
            _oldStream = stream;
            _newStream = new MemoryStream();
            return _newStream;
        }

        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        {
            return null;
        }

        public override object GetInitializer(Type WebServiceType)
        {
            return null;
        }

        public override void Initialize(object initializer)
        {

        }

        public override void ProcessMessage(SoapMessage message)
        {
            switch (message.Stage)
            {
                case SoapMessageStage.BeforeSerialize:
                    //TestRequest(message);
                    break;
                case SoapMessageStage.AfterSerialize:
                    WriteRequest(message);
                    break;
                case SoapMessageStage.BeforeDeserialize:
                    WriteResponse(message);
                    break;
                case SoapMessageStage.AfterDeserialize:
                    break;
                default:
                    throw new Exception("invalidstage");
            }
        }

        public void WriteRequest(SoapMessage message)
        {
            try
            {
                _newStream.Position = 0;

                TextReader reader = new StreamReader(_newStream);
                string methodName = message.MethodInfo.ToString();
                string reqLog = reader.ReadToEnd();

                //@@ Async log
                Task t = Task.Factory.StartNew(() =>
                {
                    try
                    {

                        WebSvcLogger.Logger.Information(string.Format("API - \"{0}\" Request:\r\n{1}", methodName, reqLog));
                    }
                    catch
                    {
                        //Log Failed
                    }
                });
            }
            catch
            {
                //Log Failed
            }
            finally
            {
                _newStream.Position = 0;
                Copy(_newStream, _oldStream);
            }
        }

        public void WriteResponse(SoapMessage message)
        {
            try
            {
                Copy(_oldStream, _newStream);
                _newStream.Position = 0;

                TextReader reader = new StreamReader(_newStream);
                string methodName = message.MethodInfo.ReturnType.FullName;                
                string respLog = reader.ReadToEnd();

                //Async run
                Task t = Task.Factory.StartNew(() =>
                {                    
                    WebSvcLogger.Logger.Information(string.Format("API - \"{0}\" Response:\r\n{1}", methodName, respLog));
                });
            }
            catch
            {
                //Log Failed
            }
            finally
            {
                _newStream.Position = 0;
            }
        }

        void Copy(Stream from, Stream to)
        {
            TextReader reader = new StreamReader(from);
            TextWriter writer = new StreamWriter(to);
            writer.WriteLine(reader.ReadToEnd());
            writer.Flush();
        }
    }

    [AttributeUsage(AttributeTargets.Method)]
    public class TraceExtensionAttribute : SoapExtensionAttribute
    {
        private int priority;

        public override Type ExtensionType
        {
            get { return typeof(TraceExtension); }
        }

        public override int Priority
        {
            get { return priority; }
            set { priority = value; }
        }
    }

新代码:

    public class HttpProtocol : IClientMessageInspector
    {

        private readonly string _serviceName;
        public HttpProtocol(string serviceName)
        {
            _serviceName = serviceName;
        }

        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            var buffer = reply.CreateBufferedCopy(Int32.MaxValue);
            reply = buffer.CreateMessage();

            WriteResponse(buffer.CreateMessage().CreateBufferedCopy(Int32.MaxValue));
        }

        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            var buffer = request.CreateBufferedCopy(Int32.MaxValue);
            request = buffer.CreateMessage();

            WriteRequest(buffer.CreateMessage().CreateBufferedCopy(Int32.MaxValue));
            return null;
        }
        public Message WriteRequest(MessageBuffer buffer)
        {
            Message msg = buffer.CreateMessage();
            StringBuilder sb = new StringBuilder();
            sb.Append(msg.ToString());

            string reqLog = sb.ToString();

            //@@ Async log
            Task t = Task.Factory.StartNew(() =>
            {
                try
                {

                    WebSvcLogger.Logger.Information(string.Format("API - \"{0}\" Request:\r\n{1}", _serviceName, reqLog));
                }
                catch
                {
                    //Log Failed
                }
            });
            return buffer.CreateMessage();
        }

        public Message WriteResponse(MessageBuffer buffer)
        {
            Message msg = buffer.CreateMessage();
            StringBuilder sb = new StringBuilder();
            sb.Append(msg.ToString());

            string respLog = sb.ToString();

            //Async run
            Task t = Task.Factory.StartNew(() =>
            {
                WebSvcLogger.Logger.Information(string.Format("API - \"{0}\" Response:\r\n{1}", _serviceName, respLog));
            });
            return buffer.CreateMessage();
        }
        private static Message Clone(Message message)
        {
            return message.CreateBufferedCopy(int.MaxValue).CreateMessage();
        }
    }

    public class TraceMessageBehavior : IEndpointBehavior
    {
        private readonly string _serviceName;
        public TraceMessageBehavior(string serviceName)
        {
            _serviceName = serviceName;
        }

        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        { }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.ClientMessageInspectors.Add(new HttpProtocol(_serviceName));
        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {

        }

        public void Validate(ServiceEndpoint endpoint)
        { }
    }

证书问题

旧方法:

    SearchServiceBinding client = new SearchServiceBinding();
    client.Url = "http://localhost/";

    //Set Basic Auth Authorization
    client.Credentials = new NetworkCredential(config.Username, config.Password);

    // Send the request
    var resp = client.service(req);

    return resp;

新方法:

    var binding = new BasicHttpBinding();
    binding.Security.Mode = BasicHttpSecurityMode.Transport;
    binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

    var address = "http://localhost/";

    ServicePortTypeClient client = new ServicePortTypeClient(binding, address);
    client.Endpoint.EndpointBehaviors.Add(new TraceMessageBehavior("Search"));

    //Set Basic Auth Authorization
    client.ClientCredentials.UserName.UserName = config.Username;
    client.ClientCredentials.UserName.Password = config.Password;

    // Send the request
    var resp = await client.serviceAsync(req);

    return resp;
]]>
后端 - 一问三不知 https://www.sapze.com/entity-framework-dbconfiguration.html Mon, 12 Jul 2021 16:42:37 +0000 https://www.sapze.com/?p=201 阅读全文 ]]> using System.Data.Entity.ModelConfiguration.Configuration; using System.Linq; using System.Collections.Generic; namespace TestCase.EntityFramework { public class TestCaseDBConfig : DbConfiguration { private static string EFFoldPath = ""; public TestCaseDBConfig() : base() { SetProviderServices("System.Data.SqlClient", System.Data.Entity.SqlServer.SqlProviderServices.Instance); EFFoldPath = AppDomain.CurrentDomain.BaseDirectory + "App_Data\\EFCache"; if (!Directory.Exists(EFFoldPath)) Directory.CreateDirectory(EFFoldPath); TestCaseDbModelStore cachedDbModelStore = new TestCaseDbModelStore(EFFoldPath); IDbDependencyResolver dependencyResolver = new SingletonDependencyResolver<DbModelStore>(cachedDbModelStore); AddDependencyResolver(dependencyResolver); } private class TestCaseDbModelStore : DefaultDbModelStore { public TestCaseDbModelStore(string location) : base(location) { } public override XDocument TryGetEdmx(Type contextType) { return LoadXml2(contextType, XDocument.Load); } private void GetConceptualAssociationNames(List<System.Data.Entity.Core.Metadata.Edm.AssociationType> lstAssociationTypes, List<string> lstNames) { int oldCount = lstNames.Distinct().ToList().Count; foreach (var association in lstAssociationTypes) { if (association.AssociationEndMembers != null && association.AssociationEndMembers.Count > 0) { var isAssociaEsixt = association.AssociationEndMembers.Where(a => lstNames.Contains(a.GetEntityType().Name)).FirstOrDefault() != null; if (isAssociaEsixt) { if (!lstNames.Contains(association.Name)) lstNames.Add(association.Name); foreach (var endMember in association.AssociationEndMembers) { if (!lstNames.Contains(endMember.GetEntityType().Name)) lstNames.Add(endMember.GetEntityType().Name); } } } } if (oldCount != lstNames.Distinct().Count()) { GetConceptualAssociationNames(lstAssociationTypes, lstNames); } } public override void Save(Type contextType, DbModel model) { if (contextType.GenericTypeArguments != null && contextType.GenericTypeArguments.Length > 0) { string name = contextType.GenericTypeArguments[0].Name; List<string> storeModelNames = new List<string>(); storeModelNames.Add(name); storeModelNames.Add("Entities"); #region StoreModel List<string> storeModelAssociates = new List<string>(); if (model.StoreModel.AssociationTypes != null && model.StoreModel.AssociationTypes.Count() > 0) { GetConceptualAssociationNames(model.StoreModel.AssociationTypes.ToList(), storeModelNames); var removedStoreAssociates = model.StoreModel.AssociationTypes.Where(a => !storeModelNames.Contains(a.Name)).ToList(); foreach (var removedAssociate in removedStoreAssociates) { var tmp = model.StoreModel.AssociationTypes.Where(a => a.Name == removedAssociate.Name).FirstOrDefault(); if (tmp != null) { model.StoreModel.RemoveItem(tmp); } } } storeModelNames = storeModelNames.Distinct().ToList(); var removedStoreModels = model.StoreModel.EntityTypes.Where(a => !storeModelNames.Contains(a.Name)).ToList(); foreach (var removedStoreModel in removedStoreModels) { var tmp = model.StoreModel.EntityTypes.Where(a => a.Name == removedStoreModel.Name).FirstOrDefault(); if (tmp != null) { model.StoreModel.RemoveItem(tmp); } } var removeEntitySetBase = model.StoreModel.Container.BaseEntitySets.Where(a => !storeModelNames.Contains(a.ElementType.Name)).ToList(); foreach (var removedStoreModel in removeEntitySetBase) { var tmp = model.StoreModel.Container.BaseEntitySets.Where(a => a.Name == removedStoreModel.Name).FirstOrDefault(); if (tmp != null) { model.StoreModel.Container.RemoveEntitySetBase(tmp); } } #endregion #region ConceptualModel List<string> conceptualAssociates = new List<string>(); if (model.ConceptualModel.AssociationTypes != null && model.ConceptualModel.AssociationTypes.Count() > 0) { GetConceptualAssociationNames(model.ConceptualModel.AssociationTypes.ToList(), storeModelNames); var removedStoreAssociates = model.ConceptualModel.AssociationTypes.Where(a => !storeModelNames.Contains(a.Name)).ToList(); foreach (var removedAssociate in removedStoreAssociates) { var tmp = model.ConceptualModel.AssociationTypes.Where(a => a.Name == removedAssociate.Name).FirstOrDefault(); if (tmp != null) { model.ConceptualModel.RemoveItem(tmp); } } } storeModelNames = storeModelNames.Distinct().ToList(); var conceptualStoreModels = model.ConceptualModel.EntityTypes.Where(a => !storeModelNames.Contains(a.Name)).ToList(); foreach (var removedStoreModel in conceptualStoreModels) { var tmp = model.ConceptualModel.EntityTypes.Where(a => a.Name == removedStoreModel.Name).FirstOrDefault(); if (tmp != null) { model.ConceptualModel.RemoveItem(tmp); } } var removeConcepEntitySetBase = model.ConceptualModel.Container.BaseEntitySets.Where(a => !storeModelNames.Contains(a.ElementType.Name)).ToList(); foreach (var removedStoreModel in removeConcepEntitySetBase) { var tmp = model.ConceptualModel.Container.BaseEntitySets.Where(a => a.Name == removedStoreModel.Name).FirstOrDefault(); if (tmp != null) { model.ConceptualModel.Container.RemoveEntitySetBase(tmp); } } #endregion #region Mapping if (model.ConceptualToStoreMapping != null && model.ConceptualToStoreMapping.EntitySetMappings != null && model.ConceptualToStoreMapping.EntitySetMappings.Count() > 0) { List<System.Data.Entity.Core.Mapping.EntitySetMapping> lstEntitySetMappings = new List<System.Data.Entity.Core.Mapping.EntitySetMapping>(); bool isMappingExists = false; foreach (var mapping in model.ConceptualToStoreMapping.EntitySetMappings) { isMappingExists = false; if (mapping.EntityTypeMappings != null && mapping.EntityTypeMappings.Count > 0) { foreach (var subMapping in mapping.EntityTypeMappings) { if (subMapping.EntityTypes != null && subMapping.EntityTypes.Count > 0) { foreach (var ef in subMapping.EntityTypes) { if (!storeModelNames.Contains(ef.Name)) { lstEntitySetMappings.Add(mapping); isMappingExists = true; break; } } } if (isMappingExists) break; } } } lstEntitySetMappings = lstEntitySetMappings.Distinct().ToList(); if (lstEntitySetMappings.Count > 0) { foreach (var tmpMapping in lstEntitySetMappings) { var tmp = model.ConceptualToStoreMapping.EntitySetMappings.Where(a => a == tmpMapping).FirstOrDefault(); if (tmp != null) { model.ConceptualToStoreMapping.RemoveSetMapping(tmp); } } } } #endregion } using (var writer = XmlWriter.Create(GetFilePath2(contextType), new System.Xml.XmlWriterSettings { Indent = true })) { EdmxWriter.WriteEdmx(model, writer); } } public string GetFilePath2(Type contextType) { var filename = (contextType.GenericTypeArguments.Length > 0 ? contextType.GenericTypeArguments[0].Name : contextType.FullName) + ".edmx"; string path = Path.Combine(EFFoldPath, filename); return path; } public override DbCompiledModel TryLoad(Type contextType) { string path = GetFilePath2(contextType); if (File.Exists(path)) { DateTime lastWriteTime = File.GetLastWriteTimeUtc(path); DateTime lastWriteTimeDomainAssembly = File.GetLastWriteTimeUtc(contextType.Assembly.Location); if (lastWriteTimeDomainAssembly > lastWriteTime) { File.Delete(path); } } return LoadXml2(contextType, reader => { var defaultSchema = GetDefaultSchema(contextType); return EdmxReader.Read(reader, defaultSchema); }); } internal T LoadXml2<T>(Type contextType, Func<XmlReader, T> xmlReaderDelegate) { var filePath = GetFilePath2(contextType); if (!File.Exists(filePath)) { return default(T); } if (!FileIsValid2(contextType, filePath)) { File.Delete(filePath); return default(T); } using (var reader = XmlReader.Create(filePath)) { return xmlReaderDelegate(reader); } } public bool FileIsValid2(Type contextType, string filePath) { var contextCreated = File.GetLastWriteTimeUtc(contextType.Assembly.Location); var storeCreated = File.GetLastWriteTimeUtc(filePath); return storeCreated >= contextCreated; } } } } ]]> 后端 - 一问三不知 https://www.sapze.com/net-core-the-signature-key-was-not-found.html Tue, 24 Dec 2019 10:26:33 +0000 https://www.sapze.com/?p=188 阅读全文 ]]> .net core使用OAuth进行验证,本地调试的时候调用接口一切正常,但是发布到IIS测试的时候一直提示401 the signature key was not found。
经过检查发现是“tempkey.rsa”文件的问题, service.AddDeveloperSigningCredential()会自动生成一个私钥文件,但是发布到IIS的时候由于域名、端口等原因,调用接口会重新生成key,造成登录生成的access_token在其它api不可用,解决方法也很简单:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options => {
        options.Authority = "http://192.168.1.1"; // 这里要是具体访问的域名
        options.Audience = "api";
        options.RequireHttpsMetadata = false;
    });

重新发布后删除根目录的 tempkey.rsa 文件,重启IIS即可。

]]>
后端 - 一问三不知 https://www.sapze.com/net-core-vue-ssr.html Thu, 20 Jun 2019 08:44:36 +0000 https://www.sapze.com/?p=173 阅读全文 ]]> 这里不再重复vue的服务端渲染逻辑,只记录一点.net core的问题

HomeController.cs

public async Task<IActionResult> Index()
{
    string path = Request.Path.Value.Trim().ToString();
    var r = await _nodeServices.InvokeAsync<string>(@"server.js", path).ConfigureAwait(false);
    return Content(r, "text/html");
}

Server.js

const fs = require('fs');
const { createBundleRenderer } = require('vue-server-renderer')

const renderer = createBundleRenderer(require('./vue-ssr-server-bundle.json'), {
    runInNewContext: false,
    template: fs.readFileSync('./index.html', 'utf-8'),
    clientManifest: require('./vue-ssr-client-manifest.json')
})

function renderToString(context) {
    //var c = JSON.parse(context.replace(/\\"/g, ""));
    //return JSON.stringify(context);
    return new Promise((resolve, reject) => {
        renderer.renderToString(context, (err, html) => {
            resolve(html);
        })
    })
}

module.exports = async (callback, data) => {
    const url = data.replace(/\\"/g, "");
    var title = 'Home';
    var d = {
        title: title,
        url: url,
        meta: '<meta name="description" content="desc" />'
    }
    var k = await renderToString(d);
    callback(null, k.toString());
}

代码其实很简单,但部署网站的时候还是遇到了一些问题,首先服务器上的.net core版本必须与vs发布所选的版本一致,否则会提示服务器500错误。
我在代码中使用了await,导致页面出现错误的时候不能及时返回,页面会显示超时,callback里面promise返回的结果添加了toString()的方法,是为了避免返回结果可能为 object object 不能由c#解析为string:“_nodeServices.InvokeAsync”。

]]>
后端 - 一问三不知 https://www.sapze.com/mvc-route-id-error.html Wed, 06 Mar 2019 08:35:15 +0000 https://www.sapze.com/?p=159 阅读全文 ]]> MVC默认的路由设置如下:

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

我们常定义的model类一般都包含"ID"字段,类似:

class Foo {
    public int Id { get; set; }
}

在Controller中我们的action也写作:

public FooController {
    [HttpPost]
    public ActionResult Edit(int id, Foo foo) {

    }
}

一般情况下并不会导致什么问题,因为从数据库的内容也是根据当前ID取出的。
特殊情况下,比如用户的权限仅限于修改ID为1的内容(任何页面都会获取ID为1的内容),当用户手动修改URL链接中的ID为2的时候,Controller读到的ID为真实ID(1),但是在View中显示的ID值确实URL中的值(2),这会导致想要修改ID为1的内容,实际上却是修改到ID为2的内容。

总结:MVC中route的ID会覆盖model中的ID,导致页面部分数据显示错误

修改方法也很简单,不使用ID为参数即可
// route

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{identifier}", // URL with parameters
    new { controller = "Home", action = "Index", identifier = UrlParameter.Optional } // Parameter defaults
);

// controller

public FooController {
    [HttpPost]
    public ActionResult Edit(int identifier, Foo foo) {

    }
}
]]>
后端 - 一问三不知 https://www.sapze.com/2017-11-17.html Mon, 16 Oct 2017 17:26:24 +0000 http://www.sapze.com/?p=132 phpize和php-config路径

/opt/cpanel/ea-php70/root/usr/bin/php-config

]]>
后端 - 一问三不知 https://www.sapze.com/resolve-iis-integrated-pipeline-mode.html Tue, 27 Jun 2017 09:17:48 +0000 http://www.sapze.com/?p=126 阅读全文 ]]> 在使用VS2013生成项目的时候提示

This operation requires IIS integrated pipeline mode.

问题说的很明确,但是基本上找不到解决的办法,谷歌和百度都说用IIS Express即可,但是这根本就解决不了我们的问题,无奈只能从配置文件下手,请看下面:

1.打开项目的.csproj文件,查看是否有这段代码

<IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>
<IISExpressWindowsAuthentication>disabled</IISExpressWindowsAuthentication>
<IISExpressUseClassicPipelineMode>true</IISExpressUseClassicPipelineMode>

如果有这段,恭喜你,找到解决方法了。首先,删除这段代码

 

2.打开项目.csproj.user(没有这个文件就直接跳过这步)文件,查看是否有跟上面一样或类似的代码,如果有,删掉它。

不想删的话,也可以改成这样

<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />

 

3.打开IISExpress配置文件,路径在 C:/Users/xx/Documents/IISExpress/config/applicationhost.config,这是一个xml文件

在节点<system.applicationHost>下找到<sites>,找到你的网站,查看节点application的属性“applicationPool”,错误的属性值是“Clr4ClassicAppPool”,我们要把它改成“Clr4IntegratedAppPool”

 

4.做完上面这些后,打开项目点击调试,项目终于正常打开了。

]]>
后端 - 一问三不知 https://www.sapze.com/soap-xml-format.html Wed, 02 Nov 2016 10:46:44 +0000 http://www.sapze.com/?p=115 阅读全文 ]]> 下面这段xml格式是一般soap的接口所返回的格式,但实际项目中的header和body部分的根节点是需要有前缀 “ns2”,实际上只需要添加一个namespace就行,但之前没有接触过。节点类似soapenv:Envelope

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <soap:Header>
  <responseHeader xmlns:ns2="http://www.org/">
   <numberOfHits>2</numberOfHits>
  </responseHeader>
 </soap:Header>
 <soap:Body>
  <getItem xmlns:ns2="http://www.org/" />
 </soap:Body>
</soap:Envelope>

百度是个坑,查到的结果大部分都是关于请求部分,很少有返回部分的例子,谷歌也搜了半天,最后终于找到解决办法。

下面的代码为 VB,C#可参照转换

<System.Xml.Serialization.XmlNamespaceDeclarations> _
    Public Property xmlns() As XmlSerializerNamespaces

        Get
            Dim xsn = New XmlSerializerNamespaces()
            xsn.Add("ns2", "http://www.org/")
            Return xsn
        End Get
        Set(value As XmlSerializerNamespaces)

        End Set
    End Property

把上面这段代码添加到需要“ns2”前缀的类里边去,比如我上面的responseHeader和getItem部分:

'''<remarks/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.17929"), _
 System.SerializableAttribute(), _
 System.Diagnostics.DebuggerStepThroughAttribute(), _
 System.ComponentModel.DesignerCategoryAttribute("code"), _
 System.Xml.Serialization.XmlTypeAttribute([Namespace]:="http://resolvingmo.ws.gs1.org/")> _
Partial Public Class getItem

    Private gepirItemField() As ItemDataLineType

    <System.Xml.Serialization.XmlNamespaceDeclarations> _
    Public Property xmlns() As XmlSerializerNamespaces

        Get
            Dim xsn = New XmlSerializerNamespaces()
            xsn.Add("ns2", "http://resolvingmo.ws.gs1.org/")
            Return xsn
        End Get
        Set(value As XmlSerializerNamespaces)

        End Set
    End Property
    '''<remarks/>
    <System.Xml.Serialization.XmlArrayAttribute(Form:=System.Xml.Schema.XmlSchemaForm.Unqualified), _
     System.Xml.Serialization.XmlArrayItemAttribute("itemDataLine", Form:=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable:=False)> _
    Public Property gepirItem() As ItemDataLineType()
        Get
            Return Me.gepirItemField
        End Get
        Set(value As ItemDataLineType())
            Me.gepirItemField = value
        End Set
    End Property
End Class

最后生成的结果就行想要的了,xml添加了指定的前缀

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <soap:Header>
  <ns2:responseHeader xmlns:ns2="http://www.org/">
   <numberOfHits>2</numberOfHits>
  </ns2:responseHeader>
 </soap:Header>
 <soap:Body>
  <ns2:getItem xmlns:ns2="http://www.org/" />
 </soap:Body>
</soap:Envelope>

]]>