web-dev-qa-db-ja.com

ODataクエリで使用される一重引用符をエスケープするにはどうすればよいですか?

ODataを使用してデータベースを照会しています。次のコード行は、「adapterName」にテキストのみが含まれている場合に正常に機能します。

ds.query('/DataAdapters?$filter=Name eq \'' + adapterName + '\'', ifmgr_CreateAdapter_Step1, onGenericFailure, '');

「adapterName」に一重引用符が含まれている場合、失敗します。次のコードを使用して、一重引用符をエスケープしてみました。

adapterName = adapterName.replace(/\'/g, '\\\'');

これはユーザー定義のテキストを正しくエスケープしますが、それでも関数は失敗します。クエリ内のテキストの正しい形式を教えてもらえますか?

30
Retrocoder

実際、%27は解決策ではありません。エスケープする正しい方法は、1つではなく2つの一重引用符を文字列に配置することです。例では"o''clock"

91
user448516

答えを少し拡張して、oDataサービス操作アクションの呼び出しにも適用できるようにしたいと思います。投稿された回答は正しいですが、サービス操作のパラメーターをエンコードする必要がある特定の順序があります。

oData Service Operationsは、有効なURL(エンコード前)がそのようになるように文字列が 'で囲まれているプリミティブ型パラメーターを受け取ります

AddString?value = 'o''clock'

これにより、サーバーは

AddString?value = 'o'

そして

'時計'

「不正なリクエスト-クエリ構文のエラー」が生成されます。

これを修正するには、URLに挿入する前に、 'をダブルエスケープしてUrlEncodeする必要があります。

URL自体をUrlエンコードしないでください。

これが機能する例です。

// value passed as "o'clock"
public async Task AddString(string value)
{
    // Escape ' with '' and UrlEncode value
    value = HttpUtility.UrlEncode(value.Replace("'", "''"));

    string url = String.Format("AddString?value='{0}'", value);

    // No need to UrlEncode url here as dynamic content has already been escaped 

    // Execute .....
}

[WebGet]
public void AddString(string value) 
{
    // here value will be "o'clock"
}
6
Mike Michaelis

実際にはoDataドキュメントで説明されています: http://docs.oasis-open.org/odata/odata/v4.01/cs01/part2-url-conventions/odata-v4.01-cs01-part2-url -conventions.html#sec_URLComponents

たとえば、これらのルールの1つは、文字列リテラル内の単一引用符が2つの連続する単一引用符として表されることです。

例3:有効なOData URL:

http:// Host/service/People ( 'O''Neil')

http:// Host/service/People(%27O%27%27Neil%27)

http:// Host/service/People%28%27O%27%27Neil%27%29

http:// Host/service/Categorys ( 'Smartphone%2FTablet')

例4:無効なOData URL:

http:// Host/service/People ( 'O'Neil')

http:// Host/service/People ( 'O%27Neil')

http:// Host/service/Categorys ( 'Smartphone/Tablet')

文字列>リテラル内の単一引用符は、2つの連続する単一引用符として表す必要があるため、最初と2番目の例は無効です。 3番目の例は、スラッシュがパスセグメントの区切り文字およびカテゴリとして解釈されるため無効です(「スマートフォンは有効なODataパスセグメントではなく、タブレットでもありません」)。

1
Ivan Zakharchuk

Wit substringofを使用する場合は、1つのアポストロフィではなく4を使用してエスケープする必要があります。

a'b -> $filter=(substringof('a''''b', FirstName))

0
Adaptabi