0

時間を節約するために、ソフトウェア プロジェクトの移行フェーズとして、既存の ASMX Web サービスを WCF インターフェイスでラップしています。System.String を返す 1 つの関数を除いて、これはうまく機能します。

元の ASMX サービスは、指定されたパラメーターに応じてテキストまたは XML を返しました。これは ASMX では問題ではありませんでした。WCF では、XML の場合、戻り値は次のようにエスケープ&lt;gml&gt;されます<gml>。下のSOAPを見てください。

リクエスト

POST http://someuri.org/WebServices/Utils.svc HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: http://www.someuri.org/IUtils/Function
Content-Length: 283
Accept: */*
User-Agent: Mozilla/4.0 (compatible; Win32; WinHttp.WinHttpRequest.5)
Host: foo.bar.org
Connection: Keep-Alive

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <Function xmlns="http://www.someri.org/">
            <type>...</type>
            <input1>...</input1>
            <input2>...</input2>
            <input3>true</input3>
        </Function >
    </s:Body>
</s:Envelope>

応答

HTTP/1.1 200 OK
Date: Fri, 04 May 2012 11:40:01 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/xml; charset=utf-8
Content-Length: 2070

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <FunctionResponse xmlns="http://www.crotec.nl/">   
            <FunctionResult>&lt;gml&gt;data&lt;/gml&gt;</FunctionResult>
        </FunctionResponse>
    </s:Body>
</s:Envelope>

いくつかのグーグルで System.IO.Stream オブジェクトを返すようになりました。

string result = DoStuff(arg1, arg2, arg3);            
byte[] bin = Encoding.UTF8.GetBytes(result);
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
return new System.IO.MemoryStream(bin);

これはある程度機能します。

string result =  "02010415DBD800D7E17577787A626978";
byte[] bin = {48,50,48,49,48,52,49,53,68,66,68,56,48,48,68,55,69,49,55,53,55,55,55,56,55,65,54,50,54,57,55,56};

ただし、SOAP メッセージで返される結果は次のとおりです。

MDIwMTA0MTVEQkQ4MDBEN0UxNzU3Nzc4N0E2MjY5Nzg=

そのため、結果の出力は文字化けしています (これも、メッセージのエンコーディング (?) が原因だと思います)。

メソッドは OperationContract を使用した attr であり、サービスは次の ABC を使用して IIS6 でホストされます。

<service name="WebServices.BeheerUtils" behaviorConfiguration="Services.ServiceBehavior">
    <!-- Service Endpoints -->
    <endpoint address="" binding="basicHttpBinding" contract="WebServices.IUtils"/>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>

出力が文字化けする理由や、HTML エンコーディングを防ぐ方法はありますか?

インターフェース

[OperationContract]
System.IO.Stream Function(string type, string input1, string input2, string input3);

実装

public new System.IO.Stream Function(string type, string input1, string input2, string input3)
{
    // Call the old ASMX method
    string result = DoStuff(type, input1, input2, input3, true);

    byte[] bin = Encoding.UTF8.GetBytes(result);
    WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
    return new System.IO.MemoryStream(bin);
}
4

4 に答える 4

1

私はこの声明に同意できません:

これは ASMX では問題ではありませんでした。WCF では、XML の場合、戻り値は次のようにエスケープ&lt;gml&gt;されます<gml>

メソッドでサービスを作成しました:

[OperationContract]
string GetXml(string str);

public string GetXml(string str)
{
    return "<gml>" + str + "</gml>";
}

そして、生成された WCF クライアントでサービスを呼び出します。

var client = new MyWcfServiceClient();
var result = client.GetXml("test");

結果は次のとおりです。

<gml>test</gml>

アップデート

これが xml の標準的な動作であることを確認するために、次のテストを実行して の値を確認してくださいrespone.FunctionResult

public class FunctionResponse
{
    public string FunctionResult { get; set; }
}

public void Test()
{
    var serialized = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<FunctionResponse>   
    <FunctionResult>&lt;gml&gt;data&lt;/gml&gt;</FunctionResult>
</FunctionResponse>";
    var ser = new XmlSerializer(typeof(FunctionResponse));
    using (var stringReader = new StringReader(serialized))
    {
        using (var xmlReader = new XmlTextReader(stringReader))
        {
            var response = ser.Deserialize(xmlReader);                    
        }
    }            
}
于 2012-05-04T11:37:55.700 に答える
1

関数が文字列を返す場合、通常はエンコードする必要があります。

XmlNode文字列ではなく を返すように関数を宣言してみてください。

于 2012-05-04T12:01:37.240 に答える
0

だから私はいくつかの戻り値の型をいじりました。これが私が思いつくことができるものです:

string result = DoStuff(type, input1, input2, input3, true);

XDocument d = new XDocument();
XDocument basis = new XDocument(new XElement("result"));

// Load the result into a XDocument, add the result as a value of the wrapper element if the format is invalid    
try
{
    d = XDocument.Parse(result);
    basis.Root.Add(d.Root);
}
catch (Exception)
{
    basis.Root.Value = result;
}    

// Return the XElement
return basis.Root;

基本的に、すべての応答を新しいルート要素にラップします。これにより、'html エンコード' ではなく、SOAP エンベロープでリテラル XML が得られます。それは私が必要とすることをしますが、私はそれが厄介だと思います. しかし、私のニーズに合った解決策が他に見つからなかったので、これを最終的な解決策として提示します。

于 2012-05-07T07:05:37.393 に答える
0

wsHttpBinding の代わりに basicHttpBinding を使用します。

于 2012-05-04T10:57:55.420 に答える