Budowanie i parsowanie adresów URL w .NET

Tworzenie i parsowanie adresów URL wykorzystując narzędzia dostarczone przez platformę .NET.

Traktowanie adresu URL jako stringa w programach jest dość wygodne jeżeli służy on tylko do przechowania adresu danego zasobu sieciowego. Jeżeli jednak takie adresy musimy generować lub wyciągać z nich niektóre parametry używanie stringa staje się nie praktyczne i wymusza na nas pisanie dodatkowych narzędzi. Wszystko w tym było by ok jeżeli pominąć fakt że framework .NET dostarcza nam właśnie zestaw klas do całej gamy operacji na adresach sieciowych.

Relacje między URI, a URL i URN.

Główną klasą odpowiedzialną za przechowywania adresów sieciowych jest klasa Uri. Jak widać nazwa klasy wskazuje, że posługujemy się URI (Uniform Resource Identifier), czyli czymś nadrzędnym niż sam URL.

Zatem platforma .NET dostarcza nam narzędzie o szerszym zastosowaniu niż budowanie samych adresów URL. Aby móc korzystać z klasy Uri jak i innych wymienionych w tym wpisie musimy do naszego projektu dodać referencję do System.ServiceModel.

Dzięki klasie Uri oprócz przechowywania danego identyfikatora sieciowego mamy możliwość weryfikacji jego poprawności przy tworzeniu takiego obiektu, jak również dostęp do poszczególnych jego części. Za pomocą tej klasy możemy tworzyć zarówno adresy względne (relative) jak i bezwzględne (absolute).

[csharp autolinks=”false”]Uri relative = new Uri("/2010/08/12/budowanie-i-parsowanie-adresow-url-w-net", UriKind.Relative);

Uri absolute = new Uri("http://blog.pietowski.com/2010/08/12/budowanie-i-parsowanie-adresow-url-w-net", UriKind.Absolute);
[/csharp]

Warto zapamiętać fakt, że obiektów klasy Uri nie można modyfikować gdyż wszystkie właściowści tej klasy umożliwiają tylko pobranie danych. Jeżeli chcemy mieć możliwość modyfikacji obiektu po jego utworzeniu powinniśmy użyć do tego celu klasy UriBuilder.

[csharp]
UriBuilder blogUri = new UriBuilder();
blogUri.Scheme = Uri.UriSchemeHttp;
blogUri.Host = "blog.pietowski.com";
blogUri.Query = "file_id=2&lang=pl";

Console.WriteLine(blogUri.Uri);
[/csharp]

Jednak najbardziej przydatną i użyteczną klasą wydaje się być UriTemplate gdyż umożliwia nam definiowanie szablonów naszego identyfikatora sieciowego. Dzięki czemu możemy np. tworzyć automatycznie wiele adresów URL z różnymi parametrami jak również pobierać wybrane parametry z gotowych już adresów.

Elementem niezbędnym do utworzenia obiektu klasy UriTemplate jest string zawierający szablon tworzonych URI, który przekazujemy do konstruktora tej klasy. Format takiego stringa może mieć różne postacie, na przykład:

  • /2010/08/12/budowanie-i-parsowanie-adresow-url-w-net
  • /2010/{mounth}/{day}/{title}
  • /{year}/*?file_id={id}
  • /{year}/{mounth}/{day}/{title}?file_id={id}
  • /{year}/{mounth}/{day}/{title}?file_id=2

Przy tworzeniu obiektu weryfikowana jest poprawność wprowadzonego formatu zatem nie musimy się martwić, że przez przypadek wprowadzimy błędne dane. Nazwy zmiennych zamiast których będą wstawiane odpowiednie wartości zapisujemy między nawiasami klamrowymi “{” “}”. Wstawienie odpowiednich wartości do adresu uzyskujemy przy pomocy metody BindByPosition(Uri, String[]) do której przekazujemy bazowy adres i wszystkie parametry w kolejności w jakiej występują w szablonie.

[csharp autolinks=”false”]UriTemplate template = new UriTemplate("/{year}/{mounth}/{day}/{title}");
Uri baseAddress = new Uri("http://blog.pietowski.com");
Uri positionalUri = template.BindByPosition(baseAddress, "2010", "08", "12","budowanie-i-parsowanie-adresow-url-w-net");
[/csharp]

Innym sposobem przekazania parametrów jest  utworzenie kolekcji NameValueCollection. Do obiektu takiej kolekcji dodajemy pary: nazwę parametru i jego wartość. Wynikowy Uri uzyskujemy wykonując metodę BindByName(Uri, NameValueCollection)do której przekazujemy bazowy adres i stworzoną kolekcję parametrów, co obrazuje poniższy przykład.

[csharp autolinks=”false”]UriTemplate template = new UriTemplate("/{year}/{mounth}/{day}/{title}");
Uri baseAddress = new Uri("http://blog.pietowski.com");

NameValueCollection parameters = new NameValueCollection();
parameters.Add("year", "2010");
parameters.Add("mounth", "08");
parameters.Add("day", "12");
parameters.Add("title", "budowanie-i-parsowanie-adresow-url-w-net");

Uri namedUri = template.BindByName(baseAddress, parameters);
[/csharp]

Szczególne znaczenie w szablonie identyfikatora URI ma gwiazdka “*”, która służy do zastępowania pozostałej część ścieżki adresu.  Symbol gwiazdki musi wystąpić raz  i musi znajdować się na końcu ścieżki tworzonego szablonu URI. Stosowanie takiego zapisu przydaje się najbardziej w czasie dopasowywania gotowych Uri do stworzonego szablonu, służy do tego metoda Match(Uri, Uri). Metoda ta zwraca obiekt klasy UriTemplateMatch, z którego możemy pobierać poszczególne parametry szablonu ze wskazanego obiektu klasy Uri. Jeżeli wskazany Uri nie pasuje do szablonu zostanie zwrócony null.

Właściwość WildcardPathSegments w klasie UriTemplateMatch umożliwia pobranie segmentów pozostałej ścieżki, którą w szablonie zastąpiliśmy “*”:

[csharp autolinks=”false”]UriTemplate template = new UriTemplate("/{year}/*?file_id={id}");
Uri baseAddress = new Uri("http://blog.pietowski.com");
Uri fullUri = new Uri("http://blog.pietowski.com/2010/08/12/budowanie-i-parsowanie-adresow-url-w-net?file_id=2");

// Match a URI to a template
UriTemplateMatch results = template.Match(baseAddress, fullUri);
if (results != null)
{
Console.WriteLine("WildcardPathSegments:");
foreach (string segment in results.WildcardPathSegments)
{
Console.WriteLine("{0}", segment);
}
}
[/csharp]

Powyższy kod zwróci nam następujący wynik:

WildcardPathSegments:
08
12
budowanie-i-parsowanie-adresow-url-w-net

Klasa UriTemplateMatch posiada poza wspomnianą powyżej wiele różnych właściwości dzięki którym możemy pobierać poszczególne elementy ścieżki, nazwy i wartości parametrów jak i wiele innych. Poniższy przykład prezentuję zastosowanie kilku z nich:

[csharp autolinks=”false”]
UriTemplate template = new UriTemplate("/{year}/{mounth}/{day}/{title}?file_id={id}&lang={lang}");
Uri baseAddress = new Uri("http://blog.pietowski.com");
Uri fullUri = new Uri("http://blog.pietowski.com/2010/08/12/budowanie-i-parsowanie-adresow-url-w-net?file_id=2&lang=pl");

UriTemplateMatch results = template.Match(baseAddress, fullUri);
if (results != null)
{
Console.WriteLine("BoundVariables:");
foreach (string variableName in results.BoundVariables.Keys)
{
Console.WriteLine("{0}: {1}",
variableName, results.BoundVariables[variableName]);
}
Console.WriteLine();

Console.WriteLine("QueryParameters:");
foreach (string queryName in results.QueryParameters.Keys)
{
Console.WriteLine("{0} : {1}",
queryName, results.QueryParameters[queryName]);
}
Console.WriteLine();

Console.WriteLine("RelativePathSegments:");
foreach (string segment in results.RelativePathSegments)
{
Console.WriteLine("{0}", segment);
}
}
[/csharp]

Po wykonaniu takiego kodu ujżymy w konsoli następujący wynik.

BoundVariables:
YEAR: 2010
MOUNTH: 08
DAY: 12
TITLE: budowanie-i-parsowanie-adresow-url-w-net
ID: 2
LANG: pl

QueryParameters:
file_id : 2
lang : pl

RelativePathSegments:
2010
08
12
budowanie-i-parsowanie-adresow-url-w-net

Teraz przed pisaniem wyrażeń regularnych czy budowaniem własnych parserów warto przemyśleć zastosowanie gotowego rozwiązania jakie dostarcza nam platforma .NET gdyż w większości przypadków może to być najlepsze wyjście, które znacznie ułatwi nam posługiwanie się adresami sieciowymi w naszej aplikacji.

Więcej informacji odnoście opisywanych klas można znaleźć na stronach MSDN.

426 thoughts on “Budowanie i parsowanie adresów URL w .NET”

  1. My wife and i have been very happy Michael managed to round up his homework using the precious recommendations he discovered while using the web site. It is now and again perplexing just to find yourself giving out things that some others might have been selling. We really realize we now have the blog owner to appreciate for this. These illustrations you made, the easy website menu, the friendships you give support to promote – it’s got mostly powerful, and it is letting our son and the family imagine that the issue is amusing, which is seriously serious. Thanks for the whole thing!

  2. I simply needed to say thanks once again. I do not know what I might have tried in the absence of these aspects discussed by you relating to my problem. This has been the fearsome crisis in my opinion, nevertheless finding out a expert mode you solved the issue took me to jump with contentment. I’m just grateful for this service and thus trust you are aware of a great job you are always undertaking educating some other people through the use of your blog. I am sure you haven’t met any of us.

  3. There are definitely lots of particulars like that to take into consideration. That could be a great point to bring up. I supply the ideas above as general inspiration but clearly there are questions like the one you carry up the place the most important thing will likely be working in trustworthy good faith. I don?t know if best practices have emerged round things like that, but I’m certain that your job is clearly identified as a good game. Both girls and boys really feel the impression of only a second抯 pleasure, for the rest of their lives.

  4. Oh my goodness! an incredible article dude. Thank you However I’m experiencing situation with ur rss . Don抰 know why Unable to subscribe to it. Is there anyone getting identical rss downside? Anybody who is aware of kindly respond. Thnkx

  5. I like the valuable information you provide in your articles.
    I will bookmark your blog and check again here frequently.
    I am quite certain I’ll learn a lot of new stuff right here!
    Good luck for the next!

  6. Very nice post. I just stumbled upon your blog and wanted to say that I’ve really enjoyed browsing your blog posts. In any case I’ll be subscribing to your rss feed and I hope you write again soon!

  7. The subsequent time I learn a weblog, I hope that it doesnt disappoint me as much as this one. I imply, I do know it was my choice to learn, but I truly thought youd have one thing attention-grabbing to say. All I hear is a bunch of whining about something that you can fix when you werent too busy on the lookout for attention.

  8. Thank you for the good writeup. It in fact was a amusement account it.

    Look advanced to far added agreeable from you!

    By the way, how can we communicate?

  9. First of all I want to say excellent blog! I had a quick question in which I’d
    like to ask if you do not mind. I was interested to know
    how you center yourself and clear your head before writing.
    I’ve had a hard time clearing my mind in getting my ideas out
    there. I do take pleasure in writing however it just seems like the first 10 to 15 minutes tend to
    be lost simply just trying to figure out how to begin. Any recommendations or tips?
    Thank you!

  10. I blog quite often and I seriously appreciate your information.
    The article has really peaked my interest. I am going to take a note of your website and keep
    checking for new information about once a week.
    I subscribed to your Feed as well.

  11. The next time I read a weblog, I hope that it doesnt disappoint me as a lot as this one. I mean, I know it was my choice to read, however I really thought youd have something interesting to say. All I hear is a bunch of whining about one thing that you may repair in the event you werent too busy on the lookout for attention.

  12. Hey there! This is my 1st comment here so I just wanted to give a quick
    shout out and tell you I truly enjoy reading your articles.
    Can you suggest any other blogs/websites/forums that go over the
    same topics? Thanks for your time!

  13. Hi, I do think this is an excellent website. I stumbledupon it 😉 I will return once
    again since i have saved as a favorite it. Money and freedom
    is the best way to change, may you be rich and continue to guide others.

  14. This design is incredible! You certainly know how to keep a reader entertained.

    Between your wit and your videos, I was almost
    moved to start my own blog (well, almost…HaHa!) Wonderful job.

    I really loved what you had to say, and more than that,
    how you presented it. Too cool!

  15. Do you have a spam problem on this blog; I also
    am a blogger, and I was wanting to know your situation; we have created some nice procedures and we
    are looking to exchange methods with other folks, why not shoot me an e-mail if interested.

Leave a Reply