MVC4 Post form null value - asp.net-mvc

I have a grid when the client click on Edit for one like a form is open. the User can Edit only some values (let the user to edit only the Shipping date for the current order) but when I send the Form the values of the non editable field are NULL on Post
When I display :
#Html.Display(model => model.Rep)
or :
#Html.TextBoxFor(model => model.ClientName, new { disabled = "disabled", #readonly = "readonly" })
the Values are displayed correctly but when I submit the form the Value are Null.
the View :
#model Models.Orders
#{
Layout = null;
}
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="~/Content/pure-release-0.5.0/pure-min.css" rel="stylesheet" />
</head>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<body>
<form class="pure-form">
<fieldset>
<legend>A Stacked Form</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-3" aria-disabled="true" aria-readonly="true">
<label for="first-name">#Html.LabelFor(model => model.Rep)</label>
#Html.Display(model => model.Rep)
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-3" aria-readonly="true">
<label for="first-name">#Html.LabelFor(model => model.ClientName)</label>
#Html.TextBoxFor(model => model.ClientName, new { disabled = "disabled", #readonly = "readonly" })
</div>
</div>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</form>
</body>
}
</html>
<script type="text/javascript">
$(document).ready(function () {
$(".Titre").click(function () {
$(this).next('.Contenu').slideToggle("slow");
});
$("#Model").prop('disabled', true);
});
</script>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}^
The model :
public class Orders
{
public int ID { get; set; }
public string Rep { get; set; }
public string ClientName { get; set; }
}
Controller :
When the User click on Edit on the Grid:
public ActionResult Edit(int id = 0)
{
Orders order = db.Orders.Find(id);
if (order == null)
{
return HttpNotFound();
}
return View(order);
}
On post:
[HttpPost]
public ActionResult Edit(Orders order)
{
if (ModelState.IsValid)
{
db.Entry(order).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(order);
}
When I debug I find theat the Values on order are NULL
I Thought that the problem was the waay that I sent data from my grid to the form but i change the easyui to Use GridMVC and still have the problem.
I used : in View TextBoxFor for readOnly + disabled as attribut but same problem
I tried :
in the Model : [ReadOnly(true)]
+ in the View : #Html.EditorFor(model => model.Rep) but I was able to edit Rep That I want to block
I tried to make the EditorFor readonly with Javascript but I was able to edit
Can you help me please, I tried all what I found but there is something missing in my code
Thanks

This is by design. Readonly values are not submitted to server (at least by modern browsers).
If you want to submit this value you can create a hidden field instead of a textbox:
#Html.HiddenFor(model => model.ClientName)
This will effectively submit your value to server

I ran into the same issue. Trying to short cut with the MVC CRUD template. I like what #PaulTaylor suggested:
Attribute [Bind(Exclude=“”)] fails to prevent over-posting

The problem is because you are using 2 forms: one nested to the other. You have to remove the second and add the css class to the first. The Html.BeginForm() will create another form.
You can try something like this:
#using (Html.BeginForm("Edit","controllerName",null,FormMethod.Post,{#class="pure-form"}))
{
#Html.ValidationSummary(true)
<body>
#Html.HiddenFor(model => model.ID)
<fieldset>
<legend>A Stacked Form</legend>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-3" aria-disabled="true" aria-readonly="true">
<label for="first-name">#Html.LabelFor(model => model.Rep)</label>
#Html.Display(model => model.Rep)
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-3" aria-readonly="true">
<label for="first-name">#Html.LabelFor(model => model.ClientName)</label>
#Html.TextBoxFor(model => model.ClientName, new { disabled = "disabled", #readonly = "readonly" })
</div>
</div>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</body>
}

Your text box is disabled. The inputs with disabled attribute set do not get submitted with the form. You can verify this by using network tab of Chrome dev tool or your favorite browser. If you want the text boxes disabled, use just readonly and not the disabled. So, your text box should be as below:
#Html.TextBoxFor(model => model.ClientName, new {#readonly = "readonly" })
Afterwards, you can use jQuery and CSS to make them look like disabled by graying them out if you like but do not use disabled if you want the values to come through.

Related

How to apply MVC validation attribute dynamically on <input type='Text'>

I have a ViewModel with [Required] and [MaxLength(4)] attribute
public class Student
{
[MaxLength(4)]
[Required]
public string Name { get; set; }
}
Inside my view I have
#model List<WebApplication2.Models.Student>
<div class="row">
<div class="col-md-4">
#{
foreach(var item in #Model)
{
#Html.TextBoxFor(model=>item.Name)
#Html.ValidationMessageFor(model => item.Name)
}
}
</div>
<div class="col-md-4">
#{
foreach (var item in #Model)
{
<input type="text" value="#item" />
}
}
</div>
When I use #Html helpers to render text boxes it applied data-validation rules to textbox. I couldn't figure out how I can apply that to normal Html <input type = 'text' /> Is there any way I can do that dynamically without using #Html helpers?

Client form validation not working with modal dialog in MVC

I am changing a create form to become a modal dialog and jquery Unobtrusive validation stops working and don't know how to fix it.
Index.cshtml has a link to trigger a modal dialog.
Create
#section scripts{
<script type="text/javascript">
$('#createCustomer').on('click', function () {
$.get('/Customer/Create', function (data) {
$('#modalContainer').html(data);
$('#myModal').modal({});
});
});
Create.cshtml is a partial view.
#model Demo.Web.Models.CustomerVm
#using (Html.BeginForm("Create", "Customer", FormMethod.Post, new { #id="createForm" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Customer</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
On the controller there is an actionmethod which returns a partial view for create form.
public ActionResult Create()
{
return PartialView("Create");
}
view modal
public class CustomerVm
{
[Required]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
before i changed it to be a modal dialog .. everything was working but now i don't know how to fix it. How can i make validation work with dialog? Obviously, I don't want to rewrite validation rules on client script .. i want to get it working from view model .. thanks.
Because the form is not added to the page when the page loads, the unobtrusive validation will not pick it up. There are two ways to fix this.
Include the form on the page during the initial load. This will cause the form to be recognized and validation will occur. You can throw the partial view in a hidden div. Then your JavaScript will just show the modal dialog.
Manually register the form with the unobtrusive validation after adding it to the page. Something like $.validator.unobtrusive.parse("#id-of-the-form");
If you are loading the dialog dynamically just register the unobtrusive validation in the containing element's change event:
$('#modal-container').change(
function() {
$.validator.unobtrusive.parse("#your-form-id");
});
In partialview of create page -> modal-header, model-body, modal-footer and javascript code in the <script>your code </script> - don't put <script>your code</script> in #section Scripts{} and it will work.
Just add the following scripts in your Create form view:
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")"
type="text/javascript">
</script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
type="text/javascript">
</script>
Adding a new comment to share a more modern solution:
Use BundleConfig.cs in the App_Start folder of your MVC project.
namespace MySolution
{
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/Site.min.css",
"~/Content/bootstrap.min.css"));
bundles.Add(new ScriptBundle("~/Scripts/js").Include(
"~/Scripts/jquery-3.3.1.min.js",
"~/Scripts/jquery.validate.min.js",
"~/Scripts/jquery.validate.unobtrusive.min.js"));
}
}
}

When I submit the partial view by either keeping the textbox filled/empty, in both cases full view is loading. How can I call Ajax to post it?

I have Area in MVC3 as mentioned below.
Model
public class AdminModule
{
[Display(Name = "MyName")]
[Required(ErrorMessage = "MyName is missing")]
public String MyName { get; set; }
}
I have Partial View with following code.
#model _1.Areas.Admin.Models.AdminModule
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "myForm" }))
{
#Html.LabelFor(i => i.MyName)
#Html.TextBoxFor(i => i.MyName)
#Html.ValidationMessageFor(i => i.MyName)
<p id="getDateTimeString">
</p>
<input type="submit" value="Click here" id="btn" />
}
View
#model _1.Areas.Admin.Models.AdminModule
#{
ViewBag.Title = "Index";
Layout = "~/Areas/Admin/Views/Shared/_LayoutPage1.cshtml";
}
<h2>
Index</h2>
<script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript">
</script>
<script type="text/javascript" src="/scripts/jquery.unobtrusive-ajax.js">
</script>
<div id="myForm">
#Html.Partial("_PartialPage1", Model)
</div>
Layout
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
</head>
<body>
<div>
#RenderBody()
</div>
</body>
</html>
Controller Actions
[HttpPost]
public ActionResult Index(AdminModule model)
{
return PartialView(model);
}
[HttpGet]
public ActionResult Index()
{
AdminModule model = new AdminModule();
model.MyName = "My Name";
return View(model);
}
Confusion
When I submit first time.
I get output like below
and form show like this. Question is - Why is index word coming two times?
When I click second time, form appearance remains same and output shows like below.
Question - Why is Jquery coming so many times ?
You could use an Ajax.BeginForm instead of a regular form. But first you should decide which section of your page you want to be updated after the AJAX call.
Let's suppose the following scenario: if the AJAX call is successful you want to update some section of your DOM with some result and if the AJAX fails you want to update the form and display the error message instead.
To implement this you could start by placing the form inside a partial (_MyForm.cshtml):
#model _1.Models.HomeModels
#using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "myForm" }))
{
#Html.LabelFor(i => i.MyName)
#Html.TextBoxFor(i => i.MyName)
#Html.ValidationMessageFor(i => i.MyName)
<input type="submit" value="Click here" id="btn" />
}
#if (Model.SomeResultProperty != null)
{
<div>#Model.SomeResultProperty</div>
}
and then you could have your main view reference this partial:
#model _1.Models.HomeModels
<div id="myForm">
#Html.Partial("_MyForm", Model)
</div>
The next step is to update your controller action that will handle the AJAX call:
[HttpPost]
public ActionResult Index(HomeModels model)
{
if (ModelState.IsValid)
{
// validation succeeded => we could set the result property
// on the model to be displayed:
model.SomeResultProperty = "this is the result";
}
return PartialView("_MyForm", model);
}
and finally you need to include the jquery.unobtrusive-ajax.js script to your page in order for the Ajax.BeginForm helper to work:
<script type="text/javascript" src="#Url.Content("~/scripts/jquery.unobtrusive-ajax.js")"></script>
Use Ajax.BeginForm instead.
Did you reference validation scripts in your page?

Using built in validation for records created on client

I have an ASP.NET MVC4 application where I'm allowing users to add 1 to many records on the client using javascript templates. It's working fine and using the right naming convention, the model binding is correctly transforming the post data into the desired collection of objects for the action method.
My question is, is there any way to use the built in MVC validation for records added using this approach. I've added data annotation attributes to my model but because I'm generating the html for each new record on the client I can't use the html helpers that typically make the process work.
Obviously, I can just add the client side validation myself and let the data annotations validate on the server but I'm wondering if there's a way to take advantage of the built in validation stack for this type of approach so I can maintain all my validation logic on the server.
For example:
The View has two form:form1 and form2。
The form1 has two part.
The first part:
There are two textbox and a Create button and a Save button.
The second part:
There are a .
so, when we fill in two textbox and press the Create button, if not pass validation, then show error messages.
if pass validation, then insert values into the and insert values to the form2.
[HttpPost] Action Create has a parameter List models.
when we press the Save button, will take values of form2 to controller mapping to List models.
Model
public class HomeModel
{
[Required]
public string Name { get; set; }
[Required]
public string Number { get; set; }
}
Controller:
[HttpPost]
public ActionResult Create(List<HomeModel> models)
{
// TODO: Add insert logic here
}
View:
#model MvcApplication1.Models.HomeModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm("Create", "Home", FormMethod.Post, new { id = "form1" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>HomeModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Number)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Number)
#Html.ValidationMessageFor(model => model.Number)
</div>
<p>
<input type="submit" value="Create" id="btnCreate" />
<input type="button" value="Save" id="btnSave" />
</p>
</fieldset>
<table id="tb"></table>
}
<div id="FormInfo" style="display: none;">
<form action="/Home/Create" id="form2" method="post"></form>
</div>
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(function () {
$("#form1").submit(function () {
var ErrorLength = $(".field-validation-error").length;
if (ErrorLength <= 0) {
var nameValue = $("#Name").val();
var numberValue = $("#Number").val();
InsertToForm2(nameValue, numberValue);
InsertToTable(nameValue, numberValue);
}
return false;
});
$("#btnSave").click(function () {
$("#form2").submit();
});
});
function InsertToForm2(nameValue, numberValue) {
var inputCount = $("#form2 input").length / 2;
var combineHTML = "<input type='text' name='models[" + inputCount + "].Name' value='" + nameValue + "' /> ";
combineHTML += "<input type='text' name='models[" + inputCount + "].Number' value='" + numberValue + "'/> ";
$("#form2").append(combineHTML);
}
function InsertToTable(nameValue, numberValue) {
var combineHTML = "<tr><td>" + nameValue + "</td><td>" + numberValue + "</td></tr>";
$("#tb").append(combineHTML);
}
</script>
}
Example Download

How to show data from two different tables in one 1 view

I'm creating a forum where user can ask questions and comment on it ....using mvc3
Inside that i have a link "details" for each question .... in side that i have 2 more links "show" and "add comments"
in show one can see all comments related to a particular Question
and in Add comments we can add a comment for particular question
its controller code is as follow:
public ActionResult Addnew(int id)
{
return View();
}
[HttpPost]
public ActionResult Addnew(Answer answr, int id)
{
answr.QuestionQId = id;
_db.Answers.Add(answr);
_db.SaveChanges();
return RedirectToAction("Index");
}
and in view i have written:
#model Hobby.Models.Answer
#{
ViewBag.Title = "Addnew";
}
<h2>Addnew</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Answer</legend>
<div class="display-label">Question</div>
<div class="display-field">
#Html.DisplayFor(model => model.Question.Que)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Ans)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Ans)
#Html.ValidationMessageFor(model => model.Ans)
</div>
<p>
<input type="submit" value="Add Comment" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
but it is not showing the Question from question table.....
Please help me
I don't see where you are binding the necessary data I think AddNew [Get] method should get the question from DB and set it to the view, I suppose you should do something similar to this
public ActionResult Addnew(int id)
{
Answer ans = new Answer();
ans.Question = _db.Questions.SingleOrDefault(q => q.Id == id);
return View(ans);
}
#Jayanga is right but I think you still wanted to show data from "2 tables" as you stated in the title of your question. Assuming you mean that you want to show the question and all related answers, and also assuming that this is .NET Entity Framework (don't know by heart the syntax of Linq2Sql), you would do:
public ActionResult Addnew(int id)
{
var question = _db.Questions.Include("Answers").SingleOrDefault(q => q.Id == id);
return View(question);
}
This changes your binding model type to Question, but I'm assuming here that a Question can have more than 1 answer, and in that case, you'll have in your View all the information you need... something like this:
// In your .cshtml file
<article class="question">#Model.Que</article> #* this is your question text *#
#foreach (var answer in Model.Answers.OrderBy(a => a.PostedDate)) { #* assuming you want to sort this *#
<article class="answer">#answer.Ans</article> #* this would be your answer text *#
}

Resources