Před nedávnem jsem v jedné Silverlight aplikaci potřeboval provést přechod z dané aplikace na určenou adresu (ekvivalent redirectu), ale metodou POST s odesláním formulářových dat. V tomto článku uvádím řešení tohoto problému.
Pokud v Silverlight aplikaci potřebujeme přejít nebo otevřít jinou URL (standardní metodou GET), používá se na to metoda HtmlPage.Window.Navigate, které jednoduše předáme cílové URL a případně určíme otevření v novém okně (nastavíme target na “_blank”) nebo jiné parametry. (Ještě upozorním na to, že tuto metodu lze zároveň použít i k navigaci uvnitř vlastní Silverlight aplikace, kdy v cílové URL měníme pouze část fragment tj. za znakem #. V takovém případě se totiž neprovádí nový GET požadavek, ale prohlížeč si pouze zaktualizuje svojí aktuální URL).
Pro “redirect” s odesláním POST dat je postup trochu odlišný. Na to musíme využít přístup přímo na objekt dokumentu aktuálního prohlížeče (který je dostupný pomoci vlastnosti HtmlPage.Document) a provést tyto akce:
- Vytvořit nový HTML formulář
- Naplnit ho potřebnými daty
- Odeslat formulář metodou submit.
Zde je pomocná metoda NavigateWithPostData, která toto provádí:
internal static class HtmlDocumentUtil
{
#region action methods
/// <summary>
/// Odeslání dat pomoci metody POST a přechod na určenou adresu
/// </summary>
/// <param name="url">URL</param>
/// <param name="values">POST data předaná jako anonymní typ</param>
/// <param name="open">true pro otevření v novém okně prohlížeče</param>
public static void NavigateWithPostData(Uri url, object values, bool open = false)
{
if (url == null)
{
throw new ArgumentNullException("url");
}
var document = System.Windows.Browser.HtmlPage.Document;
//Create a HTML form
var form = document.CreateElement("form");
form.SetAttribute("action", url.ToString());
form.SetAttribute("method", "POST");
if (open)
{
form.SetAttribute("target", "_blank");
}
document.Body.AppendChild(form);
if (values != null)
{
//Add form values
foreach (var property in values.GetType().GetProperties())
{
object value = property.GetValue(values, null);
if (value != null)
{
var input = document.CreateElement("input");
input.SetAttribute("type", "hidden");
input.SetAttribute("name", property.Name);
input.SetAttribute("value", value.ToString());
form.AppendChild(input);
}
}
}
//Submit the form
form.Invoke("submit");
document.Body.RemoveChild(form);
}
#endregion
}
Při volání této metody je potřeba určit cílovou URL HTTP POST requestu a předat data do formuláře. Pro předání těchto dat jsem zde konkrétně zvolil způsob známý z ASP.NET MVC (například u routingu), kdy jsou data předána jako instance anonymního typu tj. názvy vlastností předaného typu fungují rovnou jako klíče.
Celé volání pak může vypadat přibližně takto:
var values = new
{
SessionToken = System.Windows.Browser.HttpUtility.UrlEncode(ClientSession.CurrentSession.SessionToken)
};
HtmlDocumentUtil.NavigateWithPostData(System.Windows.Browser.HtmlPage.Document.DocumentUri, values);