Access to current AntiForgeryToken to HtmlHelper - asp.net-mvc

Can I access to current AntiForgeryToken that generated in view to HtmlHelper extention method?
Something like this:
public static string AntiForgeryTokenValue(this HtmlHelper helper)
{
}

You can get current anti forgery token value from incoming request... like below
MVC keeps this value in hidden form field with name __RequestVerificationToken...
HttpContext.Current.Request.Headers["__RequestVerificationToken"]
You can also get in client side like below :-
$('input[name="__RequestVerificationToken"]').val()
(But why do you need its value in HtmlHelper while rendering view)

Related

Why does the view get two different Model.Id? [duplicate]

This is a follow on from the following question:
MVC 3 + $.ajax - response seems to be caching output from partial view
There is a detailed description of the problem over there. However, I have now managed to narrow down the problem, that seems to be with the Html.EditorFor helpers, hence the new question.
The issue:
I post data to the server using $.ajax, then return the html of the partial view that holds the input controls. The problem is that, despite passing a newly created object to the Partial Views model, the various #Html.EditorFor and #Html.DropDownListFor helpers return the OLD DATA!.
I can prove that the model has correctly passed in a new object to the helpers, by printing the value out beside the Html helper. Ie:
#Html.EditorFor(model => model.Transaction.TransactionDate)
#Model.Transaction.TransactionDate.ToString()
As the following image shows, the #Html.EditorFor is returning the wrong data:
[Note that the value beside the Comentario text box is a date time, because I was testing replacing the default values with a value that would change with each post, ie, a DateTime.]
If I replace the #Html.EditorFor for TransactionDate with a plain old #Html.TextBox():
#Html.TextBox("Transaction_TransactionDate", Model.Transaction.TransactionDate)
Then it renders the correct TransactionDate value for a new Transaction object, ie, DateTime.MinValue (01/01/0001...).
Therefore...
The problem is with the #Html.EditorFor helpers. The problem also happens with TextBoxFor and DropDownListFor.
The problem being that these helpers seem to cache the old value.
What am I doing wrong??!
EDIT:
I have just tried debugging in the custom Editor template for dates, and in there, ViewData.TemplateInfo.FormattedModelValue shows the correct value, ie, "01/01/0001". However, once it gets to Fiddler, the response is showing the old date, eg, "01/09/2011" in the image above.
As a result, I just think that there is some caching going on here, but I have none set up, so nothing makes any sense.
There is no caching involved here. It's just how HTML helper work. They first look at the ModelState when binding their values and then in the model. So if you intend to modify any of the POSTed values inside your controller action make sure you remove them from the model state first:
[HttpPost]
public virtual ActionResult AjaxCreate(Transaction transaction)
{
if (ModelState.IsValid)
{
service.InsertOrUpdate(transaction);
service.Save();
}
service.ChosenCostCentreId = transaction.IdCostCentre;
TransactionViewModel viewModel = new TransactionViewModel();
ModelState.Remove("Transaction");
viewModel.Transaction = new Transaction();
ModelState.Remove("CostCentre");
viewModel.CostCentre = service.ChosenCostCentre;
...
return PartialView("_Create", viewModel);
}
Even if you do not specify caching, it sometimes can occur. For my controllers which handle AJAX and JSON requests, I decorate them as follows:
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
This specifically declares no caching should occur.
UPDATE
Based on an answer Darin Dimitrov gave here, try adding the following line to your controller action:
ModelState.Clear();
i have never seen this but basically if you are using ajax to request this data, you need to set nochache: i am assuming you using jQuery.ajax here so will show the code:
$.ajax({
url: "somecontroller/someAction,
cache: false, // this is key to make sure JQUERY does not cache your request
success: function( data ) {
alert( data );
}
});
just a stab in the dark, i assume you have probably already covered this already. have you tried to create a new model first and then populate that new instance of the model with your data, and then send this to your view!
Finally not sure what DB server your using but have you check to see that DB results are not cached and that you are not just requesting SQL results from the DB cache... i dont use MsSQL but i hear that it has outputCaching until something is change on the DB server itself?? anyway just a few thoughts
This was unexpected behavior for me, and although I understand the reason why it's necessary to give ModelState precedence, I needed a way to remove that entry so that the value from Model is used instead.
Here are a couple methods I came up with to assist with this. The RemoveStateFor method will take a ModelStateDictionary, a Model, and an expression for the desired property, and remove it.
HiddenForModel can be used in your View to create a hidden input field using only the value from the Model, by first removing its ModelState entry. (This could easily be expanded for the other helper extension methods).
/// <summary>
/// Returns a hidden input field for the specified property. The corresponding value will first be removed from
/// the ModelState to ensure that the current Model value is shown.
/// </summary>
public static MvcHtmlString HiddenForModel<TModel, TProperty>(this HtmlHelper<TModel> helper,
Expression<Func<TModel, TProperty>> expression)
{
RemoveStateFor(helper.ViewData.ModelState, helper.ViewData.Model, expression);
return helper.HiddenFor(expression);
}
/// <summary>
/// Removes the ModelState entry corresponding to the specified property on the model. Call this when changing
/// Model values on the server after a postback, to prevent ModelState entries from taking precedence.
/// </summary>
public static void RemoveStateFor<TModel, TProperty>(this ModelStateDictionary modelState, TModel model,
Expression<Func<TModel, TProperty>> expression)
{
var key = ExpressionHelper.GetExpressionText(expression);
modelState.Remove(key);
}
Call from a controller like this:
ModelState.RemoveStateFor(model, m => m.MySubProperty.MySubValue);
or from a view like this:
#Html.HiddenForModel(m => m.MySubProperty.MySubValue)
It uses System.Web.Mvc.ExpressionHelper to get the name of the ModelState property. This is especially useful when you have "Nested" models since the key name isn't obvious.
Make sure you're not doing this:
#Html.EditorFor(model => model.Transaction.TransactionDate.Date)
I did this, and the model never got the value back. It worked perfectly once I remove the .Date.

Sitefinity CMS: Html.BeginFormSitefinity with external URL?

I'm hoping someone can help me here - I'm trying to set up a basic MVC widget for Sitefinity that will POST to an external URL to log the user in there. The problem is if I use regular HTML to do this, the widget will only work in pure MVC mode thanks to the way WebForms deals with forms.
I googled around a bit and found people explaining that with the regular "BeginForm" you can specify an external action URL thusly:
Html.BeginForm(null, null, FormMethod.Post, new { #action="EXTERNAL_URL" })
Which produces the following opening form tag:
<form action="EXTERNAL_URL" method="post">
This works very nicely, but still outputs a regular HTML form which doesn't work with Sitefinity, so Sitefinity has it's own method to produce forms that will work in Hybrid mode "Html.BeginFormSitefinity". This method has all of the same overrides but doesn't behave in quite the same way - when I attempt to use this code:
Html.BeginFormSitefinity(null, null, FormMethod.Post, new { #action="EXTERNAL_URL" })
This produces the following opening form tag:
<form action="/TestProject/TestPage/Index" method="POST" name="defaultForm" action="EXTERNAL_URL">
As you can see, it's popping a second action attribute in rather than overriding the action attribute as seen in the default MVC method's behaviour.
I'm hoping that someone with a better understanding of how Sitefinity works might be able to provide some advice here?
Looking at the sources of the HybridForm, it cannot be modified so it will take action htmlAttribute into account: http://pastebin.com/5dfQdzs8
So you may create your own form based on this code.
You'll need html helper:
public static MyHybridForm BeginFormSitefinity(this HtmlHelper htmlHelper, string actionName, string formName, FormMethod method, IDictionary<string, object> htmlAttributes)
{
return new MyHybridForm(htmlHelper.ViewContext, actionName, formName, method, (object) htmlAttributes);
}
and override GenerateActionUrl() in your MyHybridForm by using action htmlAttribute into account.

Get Current View's Url with HtmlHelper in ASP.NET MVC 3

I ask a similar question here I think this is a really easy one (of course not for me). I have a extension method for Html helper and I need to get current view's url with HtmlHelper. Does anyone have any idea about it?
Based on your comment and the original thread you linked to I think you want to use a Url helper to get the URL for the form action, but I could have misunderstood what you wanted:
In a View:
#Url.Action(null) returns the current controller/action
#Url.Action("Action") returns a custom action with current controller
#Url.Action("Action","Controller") returns a custom controller and action
In a HTML Helper:
public static MvcHtmlString MySpecialHelper(this HtmlHelper htmlHelper)
{
UrlHelper urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext,htmlHelper.RouteCollection);
string url = urlHelper.Action("Controller","Action");
//To get the action based on the current Action/Controller use:
url = urlHelper.Action(htmlHelper.ViewData["action"] as string);
//or
url = urlHelper.Action(null);
return new MvcHtmlString(url);
}
if you want to get information about the route information , like the controller or action method that are called
you can access the RouteData dictionary from the ViewContext Object
will be like this
#ViewContext.RouteData.Values["Controller"]
with the RouteData Dictionary you can get all the info needed about the controller , action and extra parameters' name , depending on what you want
If you just want the requested url then you can just get it via the Request.Url object. This returns a Uri, but if you want the raw url then Request.RawUrl.
Necromancing
public static MvcHtmlString MyHelper(this HtmlHelper htmlHelper)
{
var url = htmlHelper.ViewContext.HttpContext.Request.Url;
//more code
}
The OP asked about "extension method for Html helper" - so yeah, this is it.
You could use the Request.RawUrl property or Request.Url.ToString() or Request.Url.AbsoluteUri.
You can use a Html Helper passing the object page as reference, like this:
#helper GoHome(WebViewPage page)
{
}
An in the View just use:
#Links.GoHome(this)

Given htmlHelper + action name, how to figure out controller name?

How does HtmlHelper.ActionLink(htmlhelper,string linktext,string action) figures out correct route?
If i have this=>
HtmlHelper.ActionLink("Edit","Edit")
Mvc automatically finds out correct route.
i.e. - if controller was Product, it will render anchor with href product/edit.
So - how to figure out controller name when i got htmlHelper + action name combo?
If your HtmlHelper looks something like:
public static string MyHelper(this HtmlHelper htmlHelper,
... some more parameters ...) {
return ... some stuff ...
}
Then from your helper, access:
RouteData routeData = htmlHelper.ViewContext.RouteData;
string controller = routeData.GetRequiredString("controller");
The RouteData object contains all the values that were processed by ASP.NET Routing for the current request. This will include the parameter names and values from the route, such as "{controller}/{action}/{id}". Many of the built-in ASP.NET MVC helpers grab "ambient" data from there so that the developer doesn't have to type them in for every helper they use.
You can also download the full source code to ASP.NET MVC from here:
ASP.NET MVC 1.0 RTM source code
ASP.NET MVC 2 Release Candidate source code

How does ASP.Net MVC ActionLink Work?

I am trying to write my own LightWeight MVC for .Net 2.0 using NHaml as the view engine.
In ASP.Net 3.5 MVC the View file we used to specify the link by the code snippet.
Html.ActionLink("Add Product","Add");
In MVC binary there is no function to match this call.
I Only found:
(In class System.Web.Mvc.Html.LinkExtensions )
public static string ActionLink(this System.Web.Mvc.HtmlHelper htmlHelper,
string linkText, string actionName)
There are more similar static classes like FormExtensions, InputExtensions etc.
How does ASP.Net MVC handle it? Does it generates dynamic code for Html.ActionLink?
The ActionLink method is an extension method (hence the this before the type of the first parameter). This means you can use this method as an instance method on all HtmlHelper instances, even though it is not defined on HtmlHelper.
Html is a property on the View of type HtmlHelper. This means you can use the ActionLink extensionmethod on it.
The ActionLink method itself does nothing more than generate a link string (with regards to its arguments) and return that string.
Have you checked out the code on Codeplex? The MVC Framwork is open source, so you can dig around as much as you need to.

Resources