How to send model from view to controller with HttpUtility.HtmlEncode - asp.net-mvc

I want to send model's description from view to controller. But it is throw exception special character's warning again. I want to use HttpUtility.HtmlEncode in view without [ValidateInput(false)] in controller. It is possible ?
#model UserModel
#using (Html.BeginForm("CreateUser", "Home", FormMethod.Post))
{
#Html.TextAreaFor(HttpUtility.HtmlEncode(x => x.Description))
<button type="submit" id="btnCreate">Create</button>
}

Did you try to add [AllowHtml] attribute in your model ?
public class ViewModel
{
[AllowHtml]
public string Description { get; set; }
}
No, it isn't security bug. ASP.Net MVC has automatic HTML encoding. Razor also includes the Html.Encode method. Calling this method will be double-encoded. Therefore you can not use Html.Encode twice.

Related

Form returns null viewmodel to the Action [duplicate]

I have a model object structure with a Foo class that contains a Bar with a string value.
public class Foo
{
public Bar Bar;
}
public class Bar
{
public string Value { get; set; }
}
And a view model that uses that structure like this
public class HomeModel
{
public Foo Foo;
}
I then have a form in view that in Razor looks something like this.
<body>
<div>
#using (Html.BeginForm("Save", "Home", FormMethod.Post))
{
<fieldset>
#Html.TextBoxFor(m => m.Foo.Bar.Value)
<input type="submit" value="Send"/>
</fieldset>
}
</div>
</body>
In html that becomes.
<form action="/Home/Save" method="post">
<fieldset>
<input id="Foo_Bar_Value" name="Foo.Bar.Value" type="text" value="Test">
<input type="submit" value="Send">
</fieldset>
</form>
Finally the controller to handle the post loos like this
[HttpPost]
public ActionResult Save(Foo foo)
{
// Magic happends here
return RedirectToAction("Index");
}
My problem is that Bar in Foo is null once it hits the Save controller action (Foo is created but with an null Bar field).
I thought the model binder in MVC would be able to create the Foo and the Bar object and set the Value property as long as it looks like the above. What am I missing?
I also know my view model is a bit over complicated and could be simpler but I for what I'm trying to do I'd really help me if I could use the deeper object structure. The examples above uses ASP.NET 5.
Firstly, the DefaultModelBinder will not bind to fields so you need to use properties
public class HomeModel
{
public Foo Foo { get; set; }
}
Secondly, the helpers are generating controls based on HomeModel but you posting back to Foo. Either change the POST method to
[HttpPost]
public ActionResult Save(HomeModel model)
or use the BindAttribute to specify the Prefix (which essentially strips the value of prefix from the posted values - so Foo.Bar.Value becomes Bar.Value for the purposes of binding)
[HttpPost]
public ActionResult Save([Bind(Prefix="Foo")]Foo model)
Note also that you should not name the method parameter with the same name as one of your properties otherwise binding will fail and your model will be null.
I just discovered another reason this can happen, which is if your property is named Settings! Consider the following View model:
public class SomeVM
{
public SomeSettings DSettings { get; set; } // named this way it will work
public SomeSettings Settings { get; set; } // property named 'Settings' won't bind!
public bool ResetToDefault { get; set; }
}
In code, if you bind to the Settings property, it fails to bind (not just on post but even on generating the form). If you rename Settings to DSettings (etc) it suddenly works again.
I had the same problem and after I followed #Stephen Muecke steps I realized that the problem was caused because my inputs were disabled (I was disabling them with JQuery on document ready) as you can see it here: How do I submit disabled input in ASP.NET MVC?. At the end I used read-only instead of disabled attribute and all the values were sent successfully to the controller.
I had the same problem, but once I created a HIDDEN FIELD for the foreign-key...it all worked just fine...
FORM EXAMPLE:
#using (Html.BeginForm("save", "meter", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(model => Model.Entity.Id)
#Html.HiddenFor(model => Model.Entity.DifferentialMeter.MeterId)
#Html.HiddenFor(model => Model.Entity.LinearMeter.MeterId)
#Html.HiddenFor(model => Model.Entity.GatheringMeter.MeterId)
... all your awesome controls go here ...
}
ACTION EXAMPLE:
// POST: /Meter/Save
[HttpPost]
public ActionResult Save(Meter entity)
{
... world-saving & amazing logic goes here ...
}
PRETTY PICTURES:

Model send from PartialView to controller

I start work in asp.net-mvc and I have problem to send model from partialview to controller.
So first this is the way I create partialview
#Html.Partial("Weather", ShopB2B.Controllers.HomeController.GetWeather())
GetWeather() is controller metod that initializes first data to model. Model looks like this
public class Weather_m
{
public IEnumerable<SelectListItem> City_dropdown { get; set; }
public string Temperature { get; set; }
}
It is nesesery to DropDownListFor, and partialview looks like this
#model ShopB2B.Models.Weather_m
#using (#Html.BeginForm("GetWeatherNew", "Home", new { weather = Model }, FormMethod.Post))
{
<table>
<tr>
<td>#Html.DropDownListFor(x => x.City_dropdown, Model.Miasta_dropdown)</td>
</tr>
<tr>
<td>#Html.LabelFor(x => x.Temperature, Model.Temperatura)</td>
<td><<input type="submit" value="Send" class="submitLink" style=" height: 40px;" /></td>
</tr>
</table>
}
And here is problem because I want send this model to controller and then check which field is selected, add something, and send this model again to partialview. Any idea, how to do it?????
You really should not be getting the data for your ViewModel type on view rendering.
Your data is type of ShopB2B.Models.Weather_m. Your strongly typed partial view expects this, this is all good. But instead of getting your ShopB2B.Models.Weather_m instentiated with ShopB2B.Controllers.HomeController.GetWeather(), you should create a ViewModel and return it to your strongly typed view, say MyViewModel. This should wrap an instance of ShopB2B.Models.Weather_m. So in your main view, your view would be strongly typed for:
#model ShopB2B.Models.MyViewModel
and you render your partial view like
#Html.Partial("Weather", Model.MyWeather_m)
I usually wrap the partial view inside the form as well, like:
#using (#Html.BeginForm("GetWeatherNew", "Home", new { weather = Model }, FormMethod.Post))
{
#Html.Partial("Weather", Model.MyWeather_m)
}
Hope this helps.
You should define the property bind to Dropdown appropriately. Since, you have defined the city_dropdown defined as IEnumarable so model binding will fails while sending from data to server due to data type mismatch (at client side City_dropdown will be generated as string for select control). In this case, you should change the property of Model as follows.
public class Weather_m
{
public string City_dropdown { get; set; }
public string Temperature { get; set; }
}
And
#Html.DropDownListFor(x => x.City_dropdown, Model.Miasta_dropdown)

MVC5 ViewModel binding in HTTP GET?

I have an action like this
public ActionResult Overview(TimeAxisVM TimeAxis = null)
{
return View(new OverviewVM());
}
View model like this
public class TimeAxisVM
{
// omitted ctor
[DataType(DataType.DateTime)]
public DateTime? From { get; set; }
[DataType(DataType.DateTime)]
public DateTime? To { get; set; }
}
An editor template for the view model
#model TimeAxisVM
#using (Html.BeginForm("Overview", "Controller", FormMethod.Get))
{
#Html.EditorFor(model => model.From)
#Html.EditorFor(model => model.To)
<button type="submit">Submit</button>
}
And a view for the Overview action like this
#model OverviewVM
#Html.EditorFor(model => model.TimeAxis)
When I execute the GET request this is the query string is TimeAxis.From=22.+02.+2014&TimeAxis.To=25.+02.+2014 but once in the action TimeAxis.From and TimeAxis.To are both null.
If I change the form method to POST it immediately works as expected. From design point of view this should/has to be a GET request.
Any ideas how to make the model binding work for GET?
UPDATE:
Changing the action to
public ActionResult Overview(DateTime? From = null, DateTime? To = null)
and sending the request in this form: .../Overview/?From=22.+02.+2014&To=25.+02.+2014 works as well.
But I'd like to keep it encapsulated in the class and dont need to change the input field name - EditorFor generates them as TimeAxis.From and TimeAxis.To. I might add other properties to the ViewModel/form.
I found the answer. HTTP GET requests are culture invariant, whereas HTTP POST requests respect current culture in ASP.NET MVC.
http://weblogs.asp.net/melvynharbour/archive/2008/11/21/mvc-modelbinder-and-localization.aspx
If you want to bring the Model again into the view, you need to pass the ModelView back to the View like
return View(TimeAxis);
then, I think you do not have a controller called Controller do you? You might have a HomeController or something else, no?
in that case, please amend you form to
#using (Html.BeginForm("Overview", "Home", FormMethod.Get))
if for example you're Overview action is in the Home controller
all in all, your controller and view should be:
public ActionResult Overview(TimeAxisVM TimeAxis)
{
return View(TimeAxis);
}
and
#using (Html.BeginForm("Overview", "Home", FormMethod.Get))
{
#Html.EditorFor(Model => Model.From)
#Html.EditorFor(Model => Model.To)
<button type="submit">Submit</button>
}
here's the screencast of the code above: http://screencast.com/t/7G6ofEq0vZEo
Full source: http://ge.tt/1Uh80pK1/v/0?c

MVC Razor Form submit not working

I am trying to use a simple form to allow authorized users to modify content on select pages on an MVC3 Razor site that I'm building. I am unable to get the edit form to post correctly though.
My model is as follows:
public class WebContent
{
public virtual UInt32 id { get; set; }
public virtual String page { get; set; }
public virtual String section { get; set; }
[UIHint("tinymce_jquery_full"), AllowHtml]
public virtual String content { get; set; }
}
My Controller:
[Authorize]
public ActionResult Edit(String page, String section)
{
WebContent content = _WebContent.GetSection(page,section);
return View(content);
}
[Authorize]
[HttpPost]
public ActionResult Edit(WebContent content)
{
if (ModelState.IsValid)
{
_WebContent.Update(content);
return View("Index");
}
else return View("Index");
}
And my View:
#model SongbirdsStudios.Models.WebContent
#{
ViewBag.Title = "Edit '"+Model.page+"'Page Content";
}
<div>
<h2>Edit</h2>
#using (Html.BeginForm())
{
<fieldset>
<legend>Page Content</legend>
#Html.HiddenFor(m => m.id)
#Html.HiddenFor(m => m.page)
#Html.HiddenFor(m => m.section)
<div class="editor-label">
Content
</div>
<div class="editor-field">
#Html.EditorFor(m => m.content)
</div>
<p>
<input type="submit" value="Update" />
</p>
</fieldset>
}
</div>
The view renders correctly and displays the expected elements. The UIHint("tinymce_jquery_full") is getting picked up correctly and the TinyMCE editor appears on the page. But, when the form submits, I get an exception.
System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client (content=...)
Everything I've read indicates that the AllowHTML attribute should allow this to post, but it's not for some reason.
I can get around this by adding the [ValidateInput(false)] attribute to the HttpPost controller method. If I do that, then this exception does not occur, but the model still does not get passed to the controller. It just passes null instead. Examining the HttpContext in the debugger indicates that it is passing 4 separate values - one for each property in my model instead of passing the model class back to the controller. I can't figure out what I need to change to make this work correctly.
I'm hoping it's something simple that I missed, and someone with a better eye can see what it is.
So after further investigation into how ASP MVC maps form fields to the model class and examining the HTML emitted to the browser, I found that this was an issue with the name of the property in my WebContent class.
public virtual String content { get; set; }
The TinyMCE editor uses a content variable to define certain characteristics associated with the editor interface. This was apparently causing the HTML 'content' generated by the user input in the editor to not get mapped back to the Model property.
Simply changing the name of the property in the model class (and of course fixing the corresponding database mapping and view references) immediately fixed the problem.
public virtual String web_data_content { get; set; }
Everything else being identical, this worked perfectly with the UIHint and AllowHTML attributes.
Add this attribute on your action
[ValidateInput(false)]
This should solve your problem
if you use ie7
this may has some err
<input type="submit" value="Update" />
give the button a name

I don't understand the answer to "ASP.NET MVC3, Html.TextAreaFor without encoding?"

In "ASP.NET MVC3, Html.TextAreaFor without encoding?"
Darin Dimitrov had the answer, but I can't make it work.
Probably because I'm confused about what the #model statement at the top of a strictly typed View means.
My statement is:
#model TestTinyMCE.Models.TestBlog
When I type in his answer:
You will need to roll your own:
<textarea cols="100" id="PostBodyText" name="PostBodyText" rows="10">
#MvcHtmlString.Create(Model.PostBodyText)
</textarea>
It fails because Model is null.
How do I associate Model with the model my View is using?
I'm in a Create() view, btw, if that matters. This will also have to work in the Edit(int id) View.
Can you show us your Controller code?
It should look like:
using TestTinyMCE.Models;
public class Mycontroller : Controller
{
public ActionResult Create()
{
return View(new TestBlog());
}
public ActionResult Edit(int id)
{
var model = new TestBlog();
// Fill the model value with the entity from your datastore
return View(model);
}
}
You must set the model of your View in your controller actions. This way, you won't receive a null value in your Razor view.
In the view, I would write this:
#model TestTinyMCE.Models.TestBlog
<textarea cols="100" id="PostBodyText" name="PostBodyText" rows="10">
#Html.Raw(Model.PostBodyText)
</textarea>

Resources