.NET कोर में क्वेरी स्ट्रिंग को पार्स और संशोधित करें


113

मुझे एक पूर्ण URI दिया गया है जिसमें एक क्वेरी स्ट्रिंग है। मैं क्वेरी स्ट्रिंग के लिए मान को सुरक्षित रूप से जोड़ना चाहता हूं, और एक मौजूदा पैरामीटर को बदल सकता हूं।

मैं से निपटने के लिए &foo=barया नियमित अभिव्यक्ति का उपयोग नहीं करना पसंद करेंगे , URI भागने मुश्किल है। बल्कि मैं एक अंतर्निहित तंत्र का उपयोग करना चाहता हूं जो मुझे पता है कि यह सही ढंग से करेगा और भागने से निपटेगा।

मैं गया है पाया एक टन है कि सभी उपयोग उत्तरों की HttpUtility। हालाँकि यह ASP.NET Core है, अब और कोई System.Web असेंबली नहीं है, इस प्रकार और नहीं HttpUtility

कोर रनटाइम को लक्षित करते हुए ASP.NET कोर में ऐसा करने का उपयुक्त तरीका क्या है?


पुस्तकालय का एक विकल्प Microsoft.AspNet.WebUtiltiesहो सकता है । Mono.HttpUtility
मेसन

मैंने उसी के लिए एक पोस्ट लिखी है, यहाँ एक नज़र डालें: neelbhatt40.wordpress.com/2017/07/06/…
नील

2
अपडेट 2017: .NET कोर 2.0 में अब शामिल है HttpUtilityऔर ParseQueryStringविधि है।
केटीसीओ

जवाबों:


152

आप ASP.NET कोर 1 या 2 का उपयोग कर रहे हैं, तो आप के साथ ऐसा कर सकते हैं Microsoft.AspNetCore.WebUtilities.QueryHelpersमें Microsoft.AspNetCore.WebUtilities पैकेज।

यदि आप ASP.NET Core 3.0 या अधिक से अधिक का उपयोग कर रहे हैं, WebUtilitiesतो अब ASP.NET SDK का हिस्सा है और इसके लिए अलग नगेट पैकेज संदर्भ की आवश्यकता नहीं है।

इसे एक शब्दकोश में पार्स करने के लिए:

var uri = new Uri(context.RedirectUri);
var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query);

ध्यान दें कि ParseQueryStringSystem.Web के विपरीत , यह IDictionary<string, string[]>ASP.NET Core 1.x में या IDictionary<string, StringValues>ASP.NET Core 2.x या अधिक में टाइप का शब्दकोश देता है , इसलिए मान स्ट्रिंग्स का एक संग्रह है। यह इसी तरह से एक ही नाम के साथ कई क्वेरी स्ट्रिंग पैरामीटर को हैंडल करता है।

यदि आप क्वेरी स्ट्रिंग पर एक पैरामीटर जोड़ना चाहते हैं, तो आप एक अन्य विधि का उपयोग कर सकते हैं QueryHelpers:

var parametersToAdd = new System.Collections.Generic.Dictionary<string, string> { { "resource", "foo" } };
var someUrl = "http://www.google.com";
var newUri = Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(someUrl, parametersToAdd);

.Net core 2.2 का उपयोग करके आप क्वेरी स्ट्रिंग का उपयोग कर प्राप्त कर सकते हैं

var request = HttpContext.Request;
var query = request.query;
foreach (var item in query){
   Debug.WriteLine(item) 
}

आपको कुंजी का एक मान मिलेगा: मूल्य जोड़े - इस तरह

[0] {[companyName, ]}
[1] {[shop, ]}
[2] {[breath, ]}
[3] {[hand, ]}
[4] {[eye, ]}
[5] {[firstAid, ]}
[6] {[eyeCleaner, ]}

1
FYI करें, WebUtilities पैकेज .net कोर 1.0 के साथ संगत नहीं है। आपको Microsoft.AspNetCore.WebUtilitiesइसके बजाय आवश्यकता हो सकती है ।
Jaime

6
@Jaime बहुत बढ़िया अवलोकन! क्या आप उस अपडेट के साथ मेरे उत्तर को संपादित कर सकते हैं ताकि आपको इसका श्रेय मिल सके?
vcsjones

3
संस्करण किया। विरासत के मामले के लिए पुराने नाम स्थान को भी रखना .net संस्करण।
Jaime

1
ऐसा प्रतीत होता है कि QueryHelpers.AddQueryString का उपयोग करना स्वचालित रूप से स्ट्रिंग्स को UrlEscape करेगा - आसान।
जोश

2
वापसी प्रकार अब IDEDIA <string, StringValues> के बजाय IDEDIA <string, string []>
btlog

35

पूर्ण URI लेने के लिए सबसे आसान और सबसे सहज तरीका है और केवल ASP.NET कोर पैकेज का उपयोग करके क्वेरी स्ट्रिंग में हेरफेर करना, कुछ आसान चरणों में किया जा सकता है:

पैकेज स्थापित करें

PM> इंस्टॉल-पैकेज Microsoft.AspNetCore.WebUtilities
PM> इंस्टॉल-पैकेज Microsoft.AspNetCore.Http.Extensions

महत्वपूर्ण कक्षाएं

बस उन्हें इंगित करने के लिए, यहां दो महत्वपूर्ण कक्षाएं हैं जिनका हम उपयोग कर रहे हैं: QueryHelpers , StringValues , QueryBuilder

कोड

// Raw URI including query string with multiple parameters
var rawurl = "https://bencull.com/some/path?key1=val1&key2=val2&key2=valdouble&key3=";

// Parse URI, and grab everything except the query string.
var uri = new Uri(rawurl);
var baseUri = uri.GetComponents(UriComponents.Scheme | UriComponents.Host | UriComponents.Port | UriComponents.Path, UriFormat.UriEscaped);

// Grab just the query string part
var query = QueryHelpers.ParseQuery(uri.Query);

// Convert the StringValues into a list of KeyValue Pairs to make it easier to manipulate
var items = query.SelectMany(x => x.Value, (col, value) => new KeyValuePair<string, string>(col.Key, value)).ToList();

// At this point you can remove items if you want
items.RemoveAll(x => x.Key == "key3"); // Remove all values for key
items.RemoveAll(x => x.Key == "key2" && x.Value == "val2"); // Remove specific value for key

// Use the QueryBuilder to add in new items in a safe way (handles multiples and empty values)
var qb = new QueryBuilder(items);
qb.Add("nonce", "testingnonce");
qb.Add("payerId", "pyr_");

// Reconstruct the original URL with new query string
var fullUri = baseUri + qb.ToQueryString();

किसी भी परिवर्तन के साथ अद्यतित रहने के लिए, आप इस बारे में मेरी ब्लॉग पोस्ट देख सकते हैं: http://benjii.me/2017/04/parse-modify-query-strings-asp-net-core/


17

HttpRequestएक Queryसंपत्ति है जो IReadableStringCollectionइंटरफ़ेस के माध्यम से पार्स की गई क्वेरी स्ट्रिंग को उजागर करती है:

/// <summary>
/// Gets the query value collection parsed from owin.RequestQueryString.
/// </summary>
/// <returns>The query value collection parsed from owin.RequestQueryString.</returns>
public abstract IReadableStringCollection Query { get; }

GitHub पर यह चर्चा इसे भी इंगित करती है।


10

यह फ़ंक्शन वापसी Dictionary<string, string>करता है और Microsoft.xxxसंगतता के लिए उपयोग नहीं करता है

दोनों पक्षों में पैरामीटर एन्कोडिंग स्वीकार करता है

डुप्लिकेट कुंजियाँ स्वीकार करता है (अंतिम मान लौटाता है)

var rawurl = "https://emp.com/some/path?key1.name=a%20line%20with%3D&key2=val2&key2=valdouble&key3=&key%204=44#book1";
var uri = new Uri(rawurl);
Dictionary<string, string> queryString = ParseQueryString(uri.Query);

// queryString return:
// key1.name, a line with=
// key2, valdouble
// key3, 
// key 4, 44

public Dictionary<string, string> ParseQueryString(string requestQueryString)
{
    Dictionary<string, string> rc = new Dictionary<string, string>();
    string[] ar1 = requestQueryString.Split(new char[] { '&', '?' });
    foreach (string row in ar1)
    {
        if (string.IsNullOrEmpty(row)) continue;
        int index = row.IndexOf('=');
        if (index < 0) continue;
        rc[Uri.UnescapeDataString(row.Substring(0, index))] = Uri.UnescapeDataString(row.Substring(index + 1)); // use Unescape only parts          
     }
     return rc;
}

यह काम करता है, लेकिन आपको सबमिशन शुरू करने से पहले इंडेक्स चेक को जोड़ना चाहिए, क्योंकि संभावना है, उस पंक्ति में '=' ​​नहीं है। जो अपवाद का कारण बनता है।
तौरीब

1
धन्यवाद @Taurib मदद के लिए, बदल दिया
Wagner परेरा

1
चेतावनी: यदि क्वेरी सेट की गई है, तो यह काम नहीं करेगा क्योंकि शब्दकोश सेट है <string, string>! (उदाहरण के लिए "आइटम = 1 & आइटम = 2?") Workaraound: उपयोग IEnumerable <KeyValuePair <स्ट्रिंग, स्ट्रिंग >> या शब्दकोश <स्ट्रिंग, StringValues> .net कोर 3.1 के लिए
theCuriousOne

धन्यवाद @theCuriousOne, इस दिनचर्या में, अंतिम मान लौटाते हैं, "सरलता के लिए डुप्लिकेट कीज़ (अंतिम मान लौटाएं") को स्वीकार करते हैं, सभी मूल्यों को वापस करने के लिए आपका समाधान ठीक है।
वैगनर परेरा

1

यह नोट करना महत्वपूर्ण है कि उस समय के बाद से शीर्ष उत्तर को सही रूप में चिह्नित किया गया Microsoft.AspNetCore.WebUtilitiesहै जिसमें एक प्रमुख संस्करण अपडेट (1.xx से 2.11 तक) था।

कहा कि, यदि आप निर्माण कर रहे हैं, तो आपको netcoreapp1.1निम्नलिखित को चलाने की आवश्यकता होगी, जो नवीनतम समर्थित संस्करण को स्थापित करता है 1.1.2:

Install-Package Microsoft.AspNetCore.WebUtilities -Version 1.1.2


1

मैं इसे एक्सट्रैशन विधि के रूप में उपयोग करता हूं, किसी भी नंबर के साथ काम करता है:

public static string AddOrReplaceQueryParameter(this HttpContext c, params string[] nameValues)
    {
        if (nameValues.Length%2!=0)
        {
            throw new Exception("nameValues: has more parameters then values or more values then parameters");
        }
        var qps = new Dictionary<string, StringValues>();
        for (int i = 0; i < nameValues.Length; i+=2)
        {
            qps.Add(nameValues[i], nameValues[i + 1]);
        }
        return c.AddOrReplaceQueryParameters(qps);
    }

public static string AddOrReplaceQueryParameters(this HttpContext c, Dictionary<string,StringValues> pvs)
    {
        var request = c.Request;
        UriBuilder uriBuilder = new UriBuilder
        {
            Scheme = request.Scheme,
            Host = request.Host.Host,
            Port = request.Host.Port ?? 0,
            Path = request.Path.ToString(),
            Query = request.QueryString.ToString()
        };

        var queryParams = QueryHelpers.ParseQuery(uriBuilder.Query);

        foreach (var (p,v) in pvs)
        {
            queryParams.Remove(p);
            queryParams.Add(p, v);
        }

        uriBuilder.Query = "";
        var allQPs = queryParams.ToDictionary(k => k.Key, k => k.Value.ToString());
        var url = QueryHelpers.AddQueryString(uriBuilder.ToString(),allQPs);

        return url;
    }

उदाहरण के लिए अगले और प्रचलित लिंक एक दृश्य में:

var next = Context.Request.HttpContext.AddOrReplaceQueryParameter("page",Model.PageIndex+1+"");

var prev = Context.Request.HttpContext.AddOrReplaceQueryParameter("page",Model.PageIndex-1+"");
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.