Bring ASP.NET MVC Model Binding to ASP.NET WebForm - asp.net-mvc

In ASP.NET MVC, on [HttpPost] methods, the MVC runtime will automatically maps and transfers the data from the form fields in the front end into a View Model, based on field names.
How can I accomplish the same thing in ASP.NET WebForm?
e.g. I have an object called Person with FirstName and LastName properties.
I have a WebForm page with Textbox controls with FirstName and LastName respectively.
When pressing Submit on the form, is there a way to automatically bind FirstName and LastName to the Person object in the code-behind Button_Click event?

ASP.net 4.5 is actually going to have built in Web Forms model binding.
The Gu has a post on it and a few other things here...
http://weblogs.asp.net/scottgu/archive/2011/09/05/web-forms-model-binding-part-1-selecting-data-asp-net-vnext-series.aspx

You can do this in webforms v4.5 using model binding. It's a way we call as Ad-Hoc Model Binding where you can bind to controls without using data bound controls such as formview. I plan to blog about it but following code describes the blog in short
The following is how your markup will look.
My model has 2 properties: name and description
Name<input type="text" name="Name" value=" " id="Name" />
<br />
Description<input type="text" name="Description" value=" " id="Description" />
<br />
<asp:Button Text="Submit" runat="server" OnClick="Unnamed_Click" />
The following is the code in the button click handler.
category is my model. In this case the model binding system pulls in the value from the form value provider which looks in the form collection.
var category = new Category();
var formValueProvider = new FormValueProvider(ModelBindingExecutionContext);
TryUpdateModel(category, formValueProvider);
if (ModelState.IsValid)
{
// save changes to database
}

Perhaps the easiest way is to assign the values explicitly in the Page_Load event, whenever it is a postback. Something like this:
if (this.IsPostBack)
{
person.FirstName = FirstNameTextBox.Text;
person.LastName = LastNameTextBox.Text;
}
Or were you looking for a more declarative approach?

Take a look at Model Binder for ASP.NET Web Forms. It is doing what you want - maps postback data to class via custom attributes applied to its properties.

Related

Parse Html string with Razor

I have an application which generates dynamic html code with asp.net core tag helpers like
<input type="hidden" asp-for="Id" />
<input asp-for="Name" />
<input asp-for="IsActive" />
I return this html code from the database into the controller, I need to parse it with Razor Engine of asp.net core and of course pass a model for the engine to get data from, How can I do that?
A possible way to solve this, is by creating a custom IFileProvider that access the database.
Here is a blog post that explains how, but it's a bit older:
https://www.mikesdotnetting.com/article/301/loading-asp-net-core-mvc-views-from-a-database-or-other-location
The current offical FileProvider docs are here: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/file-providers?view=aspnetcore-2.2
This would simulate a virtual file-system with the content from the database, those views can then be used like any cshtml file (e.g. as partial view)
I ended up creating a custom file provider which get the views from the database and this link explains it
https://www.mikesdotnetting.com/article/301/loading-asp-net-core-mvc-views-from-a-database-or-other-location
Define a model
public class Model {
Id, Name...
}
and
#Html.Raw(your html template)

ASP.NET MVC Encoding Issue

I have an ASP.NET MVC app. My app is passing a name to/from the database. I've recently discovered a bug associated with ampersands (&).
In my database, I see the name "A & W".
I am displaying this value in my UI using the following:
<input id="Name" name="Name" value="#Html.Raw(Model.Name)" />
When I view the source, I can see that the following HTML gets rendered in the browser.
<input id="Name" name="Name" value="A & W" />
So far, so good. However, when I click save, and I set a breakpoint in my controller action, I can see the Name property on my Model is now "A & W". What's worse is, everytime I save it, additional amp values get added.
How do I remedy this?
Thanks!
I had a similar problem, so I used the AllowHtml attribute on my property in my model.
[AllowHtml]
public string Name { get; set; }
If you aren't using Code First, you can apply this attribute on top of your action also:
[HttpPost]
[AllowHtml]
[ValidateAntiForgeryToken]
public ActionResult Modify(ModelClass model) {}

performing searches with ASP.NET MVC

Ok, I've just started learning ASP.NET MVC after being an ASP.NET developer for awhile. I think my main problem I'm having is trying to "unlearn" ASP.NET when developing my MVC projects.
Here's my question: I have a page which has some input fields. These fields are parameters to a search I'm trying to run against a database. The user checks the boxes next to the types of items they want to see and then clicks "Search". Very simple stuff.
I'm having trouble wrapping my mind around how exactly to "postback" to the page to display the results. Is it better to use jQuery and serialize the form? Do I use my Entity Framework models I've created? What's the best way to go about
I'm really excited about MVC and the control it gives me, but I need to get over these initial obstacles if I ever want to "sell" it to my boss as the way to develop all of our web apps. Thanks for reading!
If you haven't already, consider taking a look at the NerdDinner Tutorial featured in Professional ASP.NET MVC 1.0 by Rob Conery, Scott Hanselman, Phil Haack, and Scott Guthrie. It contains a great demonstration of many of the features of ASP.NET MVC including performing a search and returning the data both through a full page post and also asynchronously using JSON.
If your inputs are inside html form element (different story if javascript is involved) - you can use default model binding (it binds route values and querystring parameters too).
<form ...>
<input type="text" name="query" />
<input type="submit" .../>
</form>
on submit it will automagically bind form values (by name) to action parameters:
public ActionResult PerformSearch(string query)
{
//whatever
}
In your case - i suspect you got inputs as checkboxes. Something like this should work:
<form...>
<input type="checkbox" name="p" value="value1" />
<input type="checkbox" name="p" value="value2" />
<input type="checkbox" name="p" value="value3" />
<input type="checkbox" name="p" value="value4" />
<input type="checkbox" name="p" value="value5" />
</form>
public ActionResult PerformSearch(string[] p)
{
//whatever
}
Only - if (form method == "GET"), URL won't look nicely. :)
To show results, make a model for your view in action and just show it through view:
public ActionResult PerformSearch(string[] p)
{
var model = _searchService(p);
return View("Results", model);
}
Views/Results.aspx
<% foreach(var bar in Model){ %>
<%= bar.Name %>
<%}%>
P.s. When considering AJAX calls, always remember that you are loosing ability to show URL + search engines don't understand JS.

View Control name concatenated with ClientID and masterpage control name in ASP.NET MVC

I am working with an ASP.NET MVC application.
I have one master page having one contentplaceholder.
I have one view placed in the contentplaceholder of master page.
I have a few textBoxes that say "name", "age" , "email" in them.
I also have a submit button in my master page.
when I click the submit button, postback event will be called in the controller.
//POST
public ActionResult Result(FormCollection Form)
{
}
If I try to access the value of the text box name using
Form["name"]
it will give me null value.
Instead
Form["$ct100$contentplaceholder1$name"]
will give me the correct value.
How can I get the value using only name?
Don't mix Web Forms with MVC
You shouldn't be using <asp:TextBox id="name" /> but rather
<%= Html.TextBox("name") %>
The input name was autogenerated for you, which you don't want to happen. Try to generate those inputs in MVC-style, like this:
<%=Html.TextBox("name")%>
or like this:
<input type="text" id="name" name="name" value="" />

How do you handle the output of a dynamically generated form in ASP.NET MVC?

Say you create a form using ASP.NET MVC that has a dynamic number of form elements.
For instance, you need a checkbox for each product, and the number of products changes day by day.
How would you handle that form data being posted back to the controller? You can't set up parameters on the action method because you don't know how many form values are going to be coming back.
Just give each checkbox a unique name value:
<input class="approveCheck" id="<%= "approveCheck" + recordId %>"
name="<%= "approveCheck" + recordId %>" type="checkbox" />
Then parse the list of form values in the Action, after submit:
foreach (var key in Request.Form.Keys)
{
string keyString = key.ToString();
if (keyString.StartsWith("approveCheck", StringComparison.OrdinalIgnoreCase))
{
string recNum = keyString.Substring(12, keyString.Length - 12);
string approvedKey = Request.Form["approveCheck" + recNum];
bool approved = !String.IsNullOrEmpty(approvedKey);
// ...
You don't need to pass form values as arguments; you can just get them from Request.Form.
One other option: write a model binder to change the list into a custom type for form submission.
Per Craig's answer.. that is safer. There are quirks to posting multiple form elements with the same name. I would add that it would be wise to wrap the logic that makes the "collection" of controls in a way similar to WebForms. Web Forms prepend the container control's name and adds an index. For example, in a Repeater the form elements inside would be named (something like) RepeaterName_Element1, RepeaterName_Element2. When you go to get the elements out, you have to use FindControl or something of the sort.
Depending on the binders you are using, this should work:
<%var i = 0;
foreach (var product (IList<ProductSelection>)ViewData["products"]) {%>
<%=Html.Hidden(string.Format("products[{0}].Id", i), product.Id)%>
<%=Html.Checkbox(string.Format("products[{0}].Selected", i))%>
<%=product.Name%><br/>
<%}%>
...which will result in HTML something like this (notice the array notation on the names):
<input name="products[0].Id" type="hidden" value="123">
<input name="products[0].Selected" type="checkbox">
Widget
<input name="products[1].Id" type="hidden" value="987">
<input name="products[1].Selected" type="checkbox">
Gadget
...and the controller method that handles the post:
public ActionResult SelectProducts(IList<ProductSelection> products)
{
...
}
Upon binding, products parameter will contain two instances of ProductSelection.
One caveat is that I have not used the new default binding for complex objects. Rather I am using either the NameValueDeserializer or CastleBind, both from MvcContrib. They both behave this way. I am guessing binding in the Beta will work the same way.
Depending on your data, you could either output a 'CheckboxList' (which is not possible in the newer versions any more) and use a string[] parameter, or you could set up multiple forms and just modify the action.

Resources