The model binding just isn't working for me - I always get NULL coming through to the controller! Any thoughts people?
Rob
Here is my action signature:
public ActionResult SearchForUser(SearchForUserModel m)
Here is my Razor header model declaration:
#model WebOne.Models.StatusIndexModel
StatusIndexModel is a composite model containing SearchForUserModel:
public class SearchForUserModel
{
[Required(ErrorMessage = "Search information required")]
[DisplayName("Contact Search")]
public string Search { get; set; }
}
Here is my Razor:
#using (Html.BeginForm("SearchForUser", "Status"))
{
<div>
<div class="editor-field">
#Html.TextBoxFor(m => m.searchForUserModel.Search)
<input type="submit" class="formbutton_small" value="Find" />
<br />
#Html.ValidationMessageFor(m => m.searchForUserModel.Search)
</div>
</div>
}
Here is the generated HTML:
<form action="/Status/SearchForUser" method="post">
<div>
<div class="editor-field">
<input data-val="true" data-val-required="Search information required" id="searchForUserModel_Search" name="searchForUserModel.Search" type="text" value="" />
<input type="submit" class="formbutton_small" value="Find" />
<br />
<span class="field-validation-valid" data-valmsg-for="searchForUserModel.Search" data-valmsg-replace="true"></span>
</div>
</div>
</form>
You need to specify the prefix:
public ActionResult SearchForUser(
[Bind(Prefix="searchForUserModel")]SearchForUserModel m
)
Related
I am trying to do a simple calculator program in asp.net MVC. I like to add two number and get the total. But I couldn't do the task. I am a beginner at asp.net MVC. code which I tried so far I attached below.
Model
namespace WebApplication30.Models
{
public class cal
{
public int no1 { get; set; }
public int no2 { get; set; }
public int tot { get; set; }
}
}
Controller
public class CalController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(cal c)
{
c.tot = c.no1 + c.no2;
return View(c);
}
}
** This is a View pass the values from the controller**
#model WebApplication30.Models.cal
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div class="row">
#using (Html.BeginForm("Index", "cal", FormMethod.Post))
{
<div class="form-group">
<label for="no">No 1</label>
<input type="text" class="form-control" id="no1" name="no1">
</div>
<div class="form-group">
<label for="pwd">No 2</label>
<input type="text" class="form-control" id="no2" name="no2">
</div>
<div class="form-group">
<label for="pwd">total</label>
<input type="text" class="form-control" id="tot" name="tot">
</div>
<button type="submit" class="btn btn-default">Submit</button>
}
</div>
enter image description here
You need to bind the input value to the cal Model. Also, need to add cal model when get index action called .
CONTROLLER
using System;
using System.Web.Mvc;
using System.Collections.Generic;
using WebApplication30.Models;
namespace WebApplication30
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View(new cal());
}
[HttpPost]
public ActionResult Index(cal c)
{
c.tot = c.no1 + c.no2;
return View(c);
}
}
}
VIEW
#model WebApplication30.Models.cal
#{
ViewBag.Title = "Index";
}
<body>
<h2>Index</h2>
<div class="row">
#using (Html.BeginForm("/Index", "Home", FormMethod.Post))
{
<div class="form-group">
<label for="no">No 1</label>
<input type="text" class="form-control" id="no1" name="no1" value="#Model.no1">
</div>
<div class="form-group">
<label for="pwd">No 2</label>
<input type="text" class="form-control" id="no2" name="no2" value="#Model.no2">
</div>
<div class="form-group">
<label for="pwd">total</label>
<input type="text" class="form-control" id="tot" name="tot" value="#Model.tot">
</div>
<button type="submit" class="btn btn-default">Submit</button>
}
</div>
</body>
NOTE: add / before Index while submitting the form it creates sometimes a problem.
DEMO
Out of boredom of writing the same boilerplate forms, I thought I'd rather write a tag helper that would produce attributes that can be processed from stock tag helpers. But, even though I managed to get my tag helper before work before form tag helpers, form tag helpers won't process the ones that I produce.
Here is the cshtml:
#model City
#{
Layout = "_Layout";
ViewData["Title"] = "Create City";
}
<form method="post" asp-action="Create">
#foreach (string propName in BaseModel.GetProperties<City>()) {
<formgroup for="#propName" />
}
<div class="form-group">
<label asp-for="Name">Name:</label>
<input class="form-control" asp-for="Name" />
</div>
<div class="form-group">
<label asp-for="Country">Country:</label>
<input class="form-control" asp-for="Country" />
</div>
<div class="form-group">
<label asp-for="Population">Population:</label>
<input class="form-control" asp-for="Population" />
</div>
<button type="submit" class="btn btn-primary">Create</button>
<a class="btn btn-secondary" asp-controller="Home" asp-action="Index">Cancel</a>
</form>
Here is the output:
<form method="post" action="/City/Create">
<div class="form-group"><label asp-for="Name"></label><input asp-for="Name" class="form-control"></div>
<div class="form-group"><label asp-for="Country"></label><input asp-for="Country" class="form-control"></div>
<div class="form-group"><label asp-for="Population"></label><input asp-for="Population" class="form-control"></div>
<div class="form-group">
<label for="Name">Name:</label>
<input class="form-control" type="text" id="Name" name="Name" value="">
</div>
<div class="form-group">
<label for="Country">Country:</label>
<input class="form-control" type="text" id="Country" name="Country" value="">
</div>
<div class="form-group">
<label for="Population">Population:</label>
<input class="form-control" type="number" data-val="true" data-val-required="The Population field is required." id="Population" name="Population" value="">
</div>
<button type="submit" class="btn btn-primary">Create</button>
<a class="btn btn-secondary" href="/">Cancel</a>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8M_6usK6CRRNkwluTiTW8uaAAfhMcU9tAxyCT7z55zQKmpUwpi_lfSDIN4FrlMo9cE3Ka9zgX4WdpXHUdlBFVGsLIw7h_cR3FjJb6Vjqnjm8mQmtKTey_9l188p9E2sKgiksO_OB6K9-F1D7SP2lX0g"></form>
Here is my tag helper:
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
namespace ViewComponents.Infrastructure.TagHelpers {
[HtmlTargetElement("formgroup", Attributes = "for", TagStructure = TagStructure.NormalOrSelfClosing)]
public class FormGroupTagHelper : TagHelper {
/// <inheritdoc />
public override int Order => -2000;
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
protected IHtmlGenerator Generator { get; }
public string For { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) {
if (context == null) {
throw new ArgumentNullException(nameof(context));
}
if (output == null) {
throw new ArgumentNullException(nameof(output));
}
// So that other tag helpers are processed after me...
var childContent = await output.GetChildContentAsync();
// Starting up...
// Replace the tag name, include the form-group bootstrap class.
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
output.Attributes.Add("class", "form-group");
PropertyInfo propInfo = ViewContext.ViewData.ModelMetadata.ModelType.GetTypeInfo().GetDeclaredProperty(For);
output.Content.AppendHtml(GenerateLabel(new Dictionary<string, string> { ["asp-for"] = propInfo.Name }));
output.Content.AppendHtml(GenerateInput(new Dictionary<string, string> { ["asp-for"] = propInfo.Name, ["class"] = "form-control" }));
}
public static IHtmlContent GenerateLabel(IReadOnlyDictionary<string, string> attrDict) {
TagBuilder tBuilder = new TagBuilder("label");
foreach (var kvp in attrDict)
tBuilder.Attributes.Add(kvp);
return tBuilder;
}
public static IHtmlContent GenerateInput(IReadOnlyDictionary<string, string> attrDict) {
TagBuilder tBuilder = new TagBuilder("input");
foreach (var kvp in attrDict)
tBuilder.Attributes.Add(kvp);
return tBuilder;
}
}
}
Any help will be appreciated.
Have a nice one!
Tag Helpers aren't processed in a specific order, so you cannot count on one being able to do something based on the output of the other. Each tag helper needs to be designed to work independently of any other, so if you need to render HTML, you'll need to handle that yourself in your tag helper. However, since you're trying to have one tag generate any kind of form field, that's going to be a heavy lift. This is basically beyond the scope of what a tag helper is intended for.
How do I configure Checkboxes in Asp.Net MVC Razor.
Since in the documentation we have the following configuration Materialize for checkboxes :
<p>
<label>
<input type = "checkbox" />
<span> Network </span>
</label>
</p>
And in Razor I could not perform this configuration.
<div class = "input-field col s12">
#Html.EditorFor (model => model.AnnualDestaque)
#Html.LabelFor (model => model.AnnualDestaque)
#Html.ValidationMessageFor (model => model.AnnualDestaque, "", new {#class = "text-danger"})
</div>
Please include model Name in your cshtml page
#model WebApplication3.Models.Test
#{
ViewBag.Title = "Home Page";
}
#using (Html.BeginForm("Save", "Home", FormMethod.Post))
{
<div class="row">
<div class="col-md-4">
#Html.TextBoxFor(m => m.EmployeeName)
#Html.CheckBoxFor(m=>m.IsSelected)
</div>
<input type="submit" value="Save" />
</div>
}
Model
public class Test
{
public string EmployeeName { get; set; }
public bool IsSelected { get; set; }
}
If you just want to have a checkbox binded with your model like that :
public class Network
{
public bool Selected { get; set; }
public string Name { get; set; }
}
Just use :
#Html.CheckBoxFor(m=>m.Selected)
#Html.LabelFor(m=>m.Name)
I was able to solve it, and I am passing the answer.
I used Html Helper Documentation Html Helper MVC
It worked perfectly without mistakes the way it's meant to be.
<div class="input-field col s12">
<label>
<input data-val="true"
data-val-required="The Advertisement field is required."
id="Advertisement"/**** m => m.Advertisement ****/
name="Advertisement"/**** m => m.Advertisement ****/
type="checkbox"
value="true" />
<span>Anuncio Destaque</span>
<input name="Advertisement" type="hidden" value="false" />
</label>
</div>
You can make it work doing this:
<label>
<input type="checkbox" name="FIELDNAME" id="FIELDNAME" value="true" class="filled-in" #(Model.FIELDNAME? "checked" : "") />
<span>#Html.DisplayNameFor(model => model.FIELDNAME)</span>
</label>
<input name="FIELDNAME" type="hidden" value="false" />
I have a login page which has a following model:
public class LoginViewModel : BaseViewModel
{
public LoginFormViewModel Form { get; set; }
}
public class LoginFormViewModel
{
[Required]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required]
public bool RememberMe { get; set; }
}
And this is the page html:
#model SocialNetwork.Web.ViewModels.LoginViewModel
#section scripts {
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
}
<h2>Login</h2>
<style>
#btn-login {
float: left;
margin-left: 14px;
}
#checkbox-remember-me {
margin-right: 15px;
}
</style>
<div class="col-md-offset-2 col-md-4">
<form asp-action="Login">
<div class="row">
<div>
<div class="form-group col-md-12">
<label asp-for="Form.UserName"></label>
<input asp-for="Form.UserName" name="UserName" class="form-control">
<span asp-validation-for="Form.UserName"></span>
</div>
</div>
</div>
<div class="row">
<div>
<div class="form-group col-md-12">
<label asp-for="Form.Password"></label>
<input asp-for="Form.Password" name="Password" class="form-control">
<span asp-validation-for="Form.Password"></span>
</div>
</div>
</div>
<div asp-validation-summary="All"></div>
<div class="row">
<div class="checkbox pull-right" id="checkbox-remember-me">
<label>
<input asp-for="Form.RememberMe" name="RememberMe">
Remember me
</label>
</div>
<button type="submit" id="btn-login" class="btn btn btn-primary">
Log In
</button>
</div>
</form>
</div>
And client side validation simply doesn't work, those <span asp-validation-for="some-property"></span> simply don't work; but <div asp-validation-summary="All"></div> does, when page refreshes, ofcourse.
I haven't changed almost anything in my _Layout.cshtml. I am sure that those scripts at the top of Login.cshtml are in that folder, and that they are being included.
The forms action in the controller takes LoginFormViewModel as it's parameter and it's all ok with it.
I have overriden the name because, otherwise, form wasn't being bound to it's model on form submition. The name of Model.Form.Password was Form_Password, and it couldn't map that into the model on submition, because in model it was called just Password.
So, I guess that must be a problem, so there must be a another way to map that form to its model on submission, right?
Not sure where you are getting the Form.Property but this is the way it should work
but the model should look like
public class LoginViewModel : BaseViewModel
{
[Required]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Required]
public bool RememberMe { get; set; }
}
And the associated html
<form asp-route-returnurl="#ViewData["ReturnUrl"]" method="post">
<h4>Use a local account to log in.</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="UseName"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<div class="checkbox">
<label asp-for="RememberMe">
<input asp-for="RememberMe" />
#Html.DisplayNameFor(m => m.RememberMe)
</label>
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-default">Log in</button>
</div>
</form>
The asp- tag helpers use the properties of the model you are using in the view..
Make sure to add
app.UseStaticFiles(); //in Configure() method of StartUp.cs class
I have a model (simplified, removing extraneous properties):
public class SubmitModel
{
[Required]
[DataType("FileUpload")]
[Display(Name = "Formatted Data File")]
public HttpPostedFileBase FormattedDataFile { get; set; }
}
A controller:
[HttpPost]
public ActionResult Submit(SubmitModel model)
{
if (this.ModelState.IsValid)
{
//...
}
return this.View(model);
}
A FileUpload view:
#{
IDictionary<string, object> htmlAttributes = Html.GetUnobtrusiveValidationAttributes(string.Empty);
}
<input type="file" id="#this.ViewData.TemplateInfo.GetFullHtmlFieldId(string.Empty)" name="#this.ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty)" #(new MvcHtmlString(htmlAttributes.ToHtmlAttributesString())) />
#Html.ValidationMessage(string.Empty)
And a simple view:
#model SubmitModel
#using (Html.BeginForm())
{
<div class="Form">
#Html.EditorForModel()
<div class="Footer">
<button class="Button" data-options='{ "icons": { "primary": "ui-icon-disk" } }'>Submit</button>
</div>
</div>
}
Which renders to this HTML:
<form action="/Data/Submit" method="post">
<div class="Form">
<div class="Item">
<div class="Label Required">Formatted Data File:</div>
<div class="Input">
<input type="file" id="FormattedDataFile" name="FormattedDataFile" data-val-required="The Formatted Data File field is required." data-val="true" />
<span class="field-validation-error" data-valmsg-for="FormattedDataFile" data-valmsg-replace="true">The value 'Test.xlsx' is invalid.</span>
</div>
</div>
<div class="Footer">
<button class="Button" data-options='{ "icons": { "primary": "ui-icon-disk" } }'>Submit</button>
</div>
</div>
</form>
Upon clicking Submit, I'm brought to the proper controller/action and my model's FormattedDataFile property is null. The ModelState is invalid, saying that "The Formatted Data File field is required." This same code worked fine in some MVC-3 projects I've done - is there anything different regarding this in MVC-4?
i think you are missing enctype="multipart/form-data" in the form
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2