We plan to show an MVC based web page inside the WPF webbrowser control. But the MVC application is implemented with Antiforgery Token, so its saying we cannot access the page. Kindly any one help to resolve by sharing the workaround.
-
what problem are you facing now ? – Frebin Francis Feb 25 '15 at 05:09
-
It simply states the internal server error "Validation of the provided anti-forgery token failed. " – KishoreInWindows Feb 25 '15 at 06:31
-
1Can you modify the mvc application???? – Nikitesh Feb 26 '15 at 09:01
-
You need to accept cookies in you WPF browser and submit the form with the cookies in headers. – trailmax Feb 26 '15 at 22:08
1 Answers
Out of the box, this scenario should work just fine. Creating a sample app with a simple controller:
public class TestController : Controller
{
public ActionResult AntiForgery()
{
return View();
}
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult AntiForgery(ViewModel model)
{
return View(model);
}
}
a simple view:
@model Mvc.Models.ViewModel
@using (Html.BeginForm("AntiForgery", "Home"))
{
@Html.AntiForgeryToken();
@Html.EditorFor(m => m.Text)
}
and a simple view model:
public class ViewModel
{
public string Text { get; set; }
}
We can load the page, enter some text into the text box, and see it returned to the AntiForgery action with the ValidateAntiForgeryToken
attribute on it.
If we create a simple WPF application with a Window and a WebBrowser control:
<Window x:Class="Wpf.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:Wpf"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<WebBrowser Name="Browser" />
</Grid>
we can have it navigate to the MVC page when it loads:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.Browser.Navigate("http://localhost:1166/Test/AntiForgery");
}
}
As before, we get the expected result, with the page posting back to our Action correctly. So why is it not working in your case?
It's hard to say exactly, but it is likely to be cookie-related. Your WPF application must accept cookies for the ValidateAntiForgeryToken
attribute to work properly, and it must be on an HttpPost
Action. The way that the AntiForgeryToken
works is that the browser is sent a cookie with a token value that must also match a hidden input in the form.
(You can look at Steve Sanderson's blog post for a nice explanation of Cross Site Request Forgery and how the AntiForgeryToken approach is used to combat it.)
You may have noticed that the WebBrowser control is very similar to Internet Explorer (same context menu, same control rendering, etc.). This is true to a certain extent, and as such, the control inherits a lot of behavior from IE with regards to security settings.
It is possible that cookies are being blocked in the WebBrowser control based on the location of the page that you are trying to load. If you were dealing with Internet Explorer by itself, you could look at the Security Zones and Privacy settings, which allow you control access to cookies. It's possible that the WPF WebBrowser control inherits from these properties, and perhaps worth checking to see whether you have the same issues in Internet Explorer.
(For more information on changing those settings you can go here.)
A perhaps more difficult route is changing the security settings for your individual application even if the default zone (or zone settings) are preventing the cookies from being persisted. This other StackOverflow question and answer talk about making sure a cookie is persisted so that content is only displayed a few times. While not exactly the same as your issue, ensuring that the cookie is saved properly should fix your issue too if cookies are the problem.
Looking around the web for other non-security reasons that this might occur, I found an article on Rick Strahl's blog that indicates that the default setting for the WebBrowser control may be using an old IE rendering engine, and at least one comment suggested that these default settings could interfere with cookies.
If cookies aren't the issue, then there are a few other things you can look at. Because the token is tied to the session, if a user sits at your WPF application for a long time, their session might expire. In that case, the page will not properly validate. Similarly, if the application pool hosting the site is recycled or IIS reset, that might also cause the session to end and thus fail validation as well.
In the end, it will be difficult to know exactly what is preventing the token from being validated properly without more information, but these are at least a few things you can try.