Submit Partial View Data with main form in asp.net MVC - asp.net-mvc

How Do I submit Data in Partial View on submit on Main View.the partial view doesn't have a separate submit button
I'm trying to Add Multiple Products to in a single Order.Each Product is Partial View.
User can add multiple Products on click of "plus sign". I want all Products to submitted when I submit the Order.
My Place Order View is
#model MyApp.Models.Order_Detail
#section scriptsection {
<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>
<script src="../../Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
$(".addProduct").live("click", function () {
$.get("AddProduct",
function (data) {
$("#Products").append(data);
HideshowMinusButton();
});
});
</script>
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Order</legend>
<div class="editor-label">
Customer
</div>
<div class="editor-field">
#Html.DropDownListFor(c=>c.Order.CustomerID,(List<SelectListItem>)ViewBag.Customers)
</div>
<div>
<fieldset id="Products">
<legend>Products</legend>
#Html.Partial("AddProduct")
</fieldset>
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Order.OrderDate)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
On Submit Button Click How Do I get all Products in my Order?
[HttpPost]
public ActionResult PlaceOrder(Order_detail Ord) //Ord Doesn't Contain Products ??
{
//Add Order to Db
return View("Success");
}

have a look at this page, i think it will be able to help you.
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
you can change your action method to
public ActionResult PlaceOrder(Order_detail Ord, Products[] products)
or use http://www.nuget.org/packages/BeginCollectionItem/ to model bind into the Order_detail model.

You can use form collection in the post method to get the data in the partial view.
[HttpPost]
public ActionResult PlaceOrder(Order_detail Ord, FormCollection fc)
{
string value = fc.getValue("textBoxName");
}
You will get the value in form collection only if the control has name property.
Ex:
<input name="users" type="text"/>
then
String Value = fc.getvalue("users");

Related

MVC4 Post form null value

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.

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"));
}
}
}

MVC 5 button click event that updates a label on the same form

Using MVC 5, is it possible to have a button click event that updates a label on the same page?
For example, if I have a structure
#using (Html.BeginForm()) {
<fieldset>
<legend>Form</legend>
<p>
#Html.TextBox("textbox1")
</p>
<p>
#Html.Label("label1")
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
}
Clicking the Submit button grabs the textbox1's value, modifies it according to the function that gets called when the submit button is clicked and then update the value of the label as the result?
Assuming my controller is called TestController.cs and this is all done on the Index page
I noticed some suggestions include using AJAX (new to me)
You don't necessarily need to use AJAX for this. All you need to do is pass the value of your label back down as part of your action result e.g.
Controller
public class TestController : Controller
{
public ActionResult Index(string label)
{
// pass label value into view
return View("Index", label ?? "");
}
[HttpPost]
public ActionResult Index(string textValue)
{
// do something with textValue
// redirect to our Index action passing the new label value
return RedirectToAction("Index", textValue);
}
}
View
#model string
#using (Html.BeginForm()) {
<fieldset>
<legend>Form</legend>
<p>
#Html.TextBox("textbox1")
</p>
<p>
#Html.Label("label", Model)
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
}
The benefit of this approach is it follows the Post/Redirect/Get pattern so if you refreshed the page it wouldn't try to re-submit the form again.
Try this :
your cshtml code :
#using (Html.BeginForm()) {
<fieldset>
<legend>Form</legend>
<p>
<input type="text" id="textbox" name="textbox"/>
</p>
<p>
<lable id ="lable"></lable>
</p>
<p>
<input type="button" id="button" value="Submit" />
</p>
</fieldset>
}
jquery :
<script type="text/javascript">
$(document).ready(function(){
$("#button").click(function(){
document.getElementById("lable").innerHTML = $("#textbox").val();
});
});
</script>
Demo :
http://jsfiddle.net/mgGj6/2/
Hopefully it works...!
Thanks.
You can also do it with Ajax by using
#Ajax.BeginForm();
helper. It would be more comfortable for end user.

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?

Unobtrusive Javascript - And Ajax Requests

I've got a simple example here. Basically a form which when submitted will reload itself via an ajax request. The problem is when this happens, the unobtrusive javascript no longer works. I assume I could add the validate and unobtrusive files in the html i get back from the ajax call, but there must be an easier way to re-wire the validators, no?
Notice I'm hijacking my submit button in order to do an AJAX request which will replace the form in the dom, from the html which is returned from the ajax request.
Model:
public class Foo
{
public int Bar { get; set; }
}
Controller:
public class FooController : Controller
{
public ActionResult Index()
{
return View(new Foo{});
}
[HttpPost]
public ActionResult Form(Foo model)
{
return View(model);
}
[HttpPost]
public ActionResult Index(Foo model)
{
return View();
}
}
Index.cshtml
#model PartialPostBackValidation.Models.Foo
#{
ViewBag.Title = "Index";
}
<h2>#Html.ActionLink("Index", "Index")</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>
<script>
$(function () {
$("body").on("click", ".ajax-submit", function () {
var form = $(this).parents("form");
$.post(
form.attr("action"),
form.serialize(),
function (html) {
form.replaceWith(html);
}
);
return false;
});
});
</script>
#{Html.RenderPartial("Form");}
Form.cshtml
#model PartialPostBackValidation.Models.Foo
#{
ViewBag.Title = "Index";
Layout = null;
}
#using (Html.BeginForm("Form", "Foo")) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Foo</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Bar)
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.Bar)
#Html.ValidationMessageFor(model => model.Bar)
</div>
<p>
<input type="submit" value="Create" class="ajax-submit" />
</p>
</fieldset>
}
To get the validation to work you simply have to re-enable it on the form once content is loaded dynamically:
$('#form-id').removeData('validator');
$('#form-id').removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse('#form-id'); <<<<<< Just having this could be enough but some people complain that without removingData first it doesn’t always work.
p.s. Ofcourse you're going to need to add an id attribute to your #using (Html.BeginForm("Form", "Foo"))

Resources