This is the model example.cs
namespace View_Partial_Editor.Models
{
public class ExampleView
{
...
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
public string Field4 { get; set; }
public string Field5 { get; set; }
...
}
}
I have this view example.cshtml:
#model View_Partial_Editor.Models.ExampleView
#{Html.RenderPartial("EditExample",Model);}
#Html.TextBoxFor(m => m.Field1)
Then i have this partialView EditExample.cshtml:
#model View_Partial_Editor.Models.ExampleView
#Html.HiddenFor(m => m.Field1)
#using (Ajax.BeginForm("EditExample", new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "partial" }))
{
<div>
#Html.EditorFor(m => m, "Editor", null)
</div>
<p>
<input id="buttona" type="submit" value="Save" />
</p>
}
I have this controller ExampleController:
namespace View_Partial_Editor.Controllers
{
public class ExampleController : Controller
{
//
// GET: /Example/
public ActionResult Example()
{
return View();
}
[HttpPost]
public ActionResult EditExample(ExampleView example)
{
example.Field1 ="7";
return View("Example", example);
}
}
}
And this is the editor that is called in the partial editor.cshtml
#model View_Partial_Editor.Models.ExampleView
<div class="editor-label">
#Html.LabelFor(m => m.Field1 )
</div>
<div class="editor-field">
#Html.EditorFor(m => m.Field1)
#Html.ValidationMessageFor(m => m.Field1)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Field2)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.Field2)
#Html.ValidationMessageFor(m => m.Field2)
</div>
My problem is that i want to modify the data of the model in the controller in the ajax call, and return the model modified to the exampleView.But when the ajax called finish the value that i change in the controller is not changed in the model
Edit: The thing that i want is to send the call to the ajax methos, save something in the database, then modify the model, and in the example view i want to have that model with the changes.
In this moment, if i replace the partial view with the result of the ajax, the model in the example view is not modified.Another way is to replace the full example view, so the model is received there, but i have to pass a lot of fields using Html.HiddenFor, is possible to make this without replacing the views only returnng the model with the changes
Try calling ModelState.Clear() in your HttpPost action method. Html helpers use the values in the ModelState first, then the Model. If you change a value in the model on a post therefore, you need to clear the value from the ModelState.
Related
I've got a model:
public class PersonViewModel
{
public int Id { get; set; }
[MaxLength(25)]
public string Firstname { get; set; }
[MaxLength(50)]
public string Surname { get; set; }
}
And a ViewModel to contain one instance and a list of the above:
public class PeopleSearchViewModel
{
public PersonViewModel Person { get; set; }
public List<PersonViewModel> People { get; set; }
}
Then my View:
#model PeopleSearchViewModel
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
#Html.LabelFor(m => m.Person.Firstname)
#Html.HiddenFor(m => m.Person.Firstname)
#Html.TextBoxFor(m => m.Person.Firstname)
#Html.ValidationMessageFor(m => m.Person.Firstname)
<input type="submit" value="Search" id="Whatever"/>
}
And finally the controller:
[HttpPost]
public ActionResult Search(PeopleSearchViewModel theModelIsntPassing)
{
}
The model is not being passed to the controller on form submission?
Or maybe it is, but the individual properties aren't populated.
The ActionResult Search method is definitely being called, just theModelIsntPassing has no values in its nested property
Not sure why you are having both HiddenFor and TextBoxFor for FirstName.
Please try comment/remove #Html.HiddenFor(m => m.Person.Firstname) statement in your view
#model PeopleSearchViewModel
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
#Html.LabelFor(m => m.Person.Firstname)
#*#Html.HiddenFor(m => m.Person.Firstname)*#
#Html.TextBoxFor(m => m.Person.Firstname)
#Html.ValidationMessageFor(m => m.Person.Firstname)
<input type="submit" value="Search" id="Whatever"/>
}
So I'm pretty new in MVC, I got Mission model:
public class Mission
{
public ObjectId _id { get; set; }
public string MissionType { get; set; }
public string ElipseNumber { get; set; }
public string MissionDate { get; set; }
public string ReminderNumber { get; set; }
public string Notes { get; set; }
}
When the user is selecting a specific mission, it goes to the view as #ViewBag.SelectedMission
Now, I want to let the user have the option to add a note to a selected mission, so using a modal I added a textbox like so:
<div class="notesLabel">
#Html.LabelFor(model => model.Notes)
</div>
<div class="notesTextBox">
#Html.TextBoxFor(model => model.Notes)
</div>
Not sure exactly what to do, How do I take the input from the textbox and adding it to the SelectedMission.Notes?
Thanks from advance.
I am also a beginner but trying to help. From what I understand you can do something like below
Contoller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Mission model)
{
var notes= model.Notes;
//Set the values to view model accordingly and save to DB eventually
}
View
#model Mission
#using (Html.BeginForm("Create", "ControllerName"))
{
#Html.AntiForgeryToken()
// ALL YOUR HTML FIELD WILL COME HERE
<div class="notesLabel">
#Html.LabelFor(model => model.Notes)
</div>
<div class="notesTextBox">
#Html.TextBoxFor(model => model.Notes)
</div>
<input type="submit" value="save">
}
Try below code. The form will submit the details entered by user on button click. Assumption: the Controller name is Home and Action name which saves the notes data is SaveNotes. When user clicks the submit button, the data is sent to the SaveNotes action in HomeController. In action function, after validation is done, values are saved into to DB. If you don't want to save to DB, you can do anything as per your logic/design. Value will be in objMission.Notes.
<% Html.BeginForm("SaveNotes", "Home", FormMethod.Post); %>
#Html.AntiForgeryToken()
:
:
<div class="notesLabel">
#Html.LabelFor(model => model.Notes)
</div>
<div class="notesTextBox">
#Html.TextBoxFor(model => model.Notes)
</div>
:
:
<input type="submit" name="submit" value="Save" />
<% Html.EndForm(); %>
public class HomeController : Controller
{
:
:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SaveNotes(Mission objMission)
{
//Set the values to view model accordingly and save to DB eventually
if (ModelState.IsValid)
{
db.Missions.Add(objMission);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(objMission);
}
:
:
}
I'm beginner in C#. When I postback the form to server its show null value in model. Pls help I have no clue what to do?
Controller Code:
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "administrator")]
public ActionResult ChangeUserDetail(ChangeUserDataModel model)
{
// ....
}
Model Code:
public class ChangeUserDataModel
{
[Display(Name = "User Name")]
public string UserName { get; set; }
[Display(Name = "Update Field")]
public string Change { get; set; }
[Required]
public string Value { get; set; }
}
View Code:
using (Html.BeginForm("ChangeUserDetail", "Home", FormMethod.Post)
{
var model2 = new Webrims.Models.AdminViewModel.ChangeUserDataModel();
<div class="form-group">
#Html.LabelFor(m => model2.UserName)
<div class="col-md-8">
#Html.DropDownListFor(m => model2.UserName, new
SelectList(ViewBag.UserNames, "Value", "Text")
</div>
</div>
.....
}
I think that this line
var model2 = new Webrims.Models.AdminViewModel.ChangeUserDataModel();
is not corrrect. Why would you need to initiate here a model?
In an MVC architecture the View receives the Model that is passed from the Controller. The View doesn't create the Model that will use later. So normally in your GET request you should pass an epmty model and on POST this model would be created based on the values that the form you POST contains.
In terms of code. The expected is something like this:
View
using (Html.BeginForm("ChangeUserDetail", "Home", FormMethod.Post)
{
<div class="form-group">
#Html.LabelFor(m => m.UserName)
<div class="col-md-8">
#Html.DropDownListFor(m => m.UserName, new
SelectList(ViewBag.UserNames, "Value", "Text")
</div>
</div>
}
Furthermore, at the top of your view you should define the type of the Model you expcet:
#model Webrims.Models.AdminViewModel.ChangeUserDataModel
Use this code in view, should work.
#model Webrims.Models.AdminViewModel.ChangeUserDataModel
using (Html.BeginForm("ChangeUserDetail", "Home", FormMethod.Post)
{
<div class="form-group">
#Html.LabelFor(m => Model.UserName)
<div class="col-md-8">
#Html.DropDownListFor(m => Model.UserName, new
SelectList(ViewBag.UserNames, "Value", "Text")
</div>
</div>
}
I am new to MVC and I am trying to understand how this whole Model binds to a view. I understood how to display any complex object using a partial view / views but I am not able to understand how to create an object of the model using a view.
We have a card to which we can add multiple transactions on the go .
Essentially what I am trying to achieve is this view to add transactions. The Add transactions button when clicked adds a partial view to the div tag on the main page. When I hit save all these transactions have to be added to the AcctCardTransaction model and then be sent to the controller. I am not able to add the UI of my page as the site does not allow me to add it . All I am trying to do is to display a partial view that binds to the model and creates a list of transactions so that the model can be used to save to the tables.
[![Add Card # and Transactions][1]][1]
Here is the model for the Card Transactions
public class AcctCardTransaction
{
public int? LastFourAcctNumber { get; set; }
public int LastFourDigCard { get; set; }
public List<Transaction> AssociatedTransactions { get; set; }
}
Transactions:
public class Transaction
{
public bool isSelected { get; set; }
public int Amount { get; set; }
public DateTime TransDateTime { get; set; }
public string Location { get; set; }
public string Desc1 { get; set; }
public string Desc2 { get; set; }
public string Desc3 { get; set; }
}
Here is the partial view to add one transaction - on to the screen
#model UI.Data.Models.Claim.Transactions.Transaction
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="row">
<div class="col-md-1">
<br />
#Html.CheckBoxFor(model => model.isSelected)
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.Amount) <label>:</label>
#Html.EditorFor(model => model.Amount)
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.TransDateTime)
#Html.EditorFor(model => model.TransDateTime)
#Html.ValidationMessageFor(model => model.TransDateTime)
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.Location)
#Html.EditorFor(model => model.Location)
#Html.ValidationMessageFor(model => model.Location)
</div>
<div class="col-md-2">
#Html.LabelFor(model => model.Desc1)
#Html.EditorFor(model => model.Desc1)
#Html.ValidationMessageFor(model => model.Desc1)
</div>
<div class="col-md-1">
<br />
Delete
</div>
</div>
[![enter image description here][1]][1]
Here is the view to add card # and transaction
#model AcctCardTransaction
#{
ViewBag.Title = "Add Transactions";
}
#using (Html.BeginForm("AddTransactions", "Prepaid"))
{
<script type="text/javascript">
$(document).ready(function () {
$("#btnAddTran").click(function () {
$.ajax({
url: '/Prepaid/AddOneTransaction',
contentType: 'application/html; charset=utf-8',
type: 'GET',
dataType: 'html'
}).success(function (result) {
$('#addTransDiv').append(result);
})
.error(function (xhr, status) {
alert(status);
});
});
});
</script>
<div class="form-inline bottom-left">
<div class="row">
#Html.Label("Last 4 digits of the card")
#Html.EditorFor(model => model.LastFourDigCard)
#Html.ValidationMessageFor(model => model.LastFourDigCard)
#* #Html.Partial( "~/Views/Shared/Partials/_addTransaction.cshtml")*#
<input id="btnAddTran" value="Add Transaction" class="btn btn-default pull-right" />
</div>
</div>
<br />
<div class="row" id="addTransDiv">
<hr />
</div>
<input type="submit" value="save" class="btn btn-default pull-right" />
}
Here is my simple controller . AddoneTransaction is the action that adds one transaction partial view to the view. In my httpPost AddTransactions action The model object does not return any transactions.
Here is my exact question. how do i bind these transactions Model objects that are returned from these partial views as a list to the main model object card transactions and from there return this to the controller?
[HttpGet]
public ActionResult AddTransactions()
{
AcctCardTransaction acctCardtran = new AcctCardTransaction();
return View(acctCardtran);
}
[HttpPost]
public ActionResult AddTransactions(AcctCardTransaction cardTrans)
{
return View();
}
public ActionResult AddOneTransaction()
{
Transaction nTran = new Transaction();
return PartialView("~/Views/Shared/Partials/_addTransaction.cshtml",nTran);
}
I tried a lot of find answer for this question and could not understand what others were talking about , I saw lots of posts on how to display an existing model with a list of objects , but here I want to create and not just display.
You are providing two different models to both views and expecting that they would be bound to one Model somehow and would return the single Model on post. It doesn't make any sense.
....but I am not able to understand how to create an object of the model using a view.
Also you are rendering your Partial view using custom javascript. So you have to write a JS method to find the form and build the model from all added partial views(transactions) and then post it to the server.
$('button.submitTransaction').click(function (e) {
// Sample to find all div containing all added transactions type
var form = $('#AddTransactions').find('form');
// validate the form
var v = $(form).valid();
if (v === true) {
var transactionsContainer = $('#AddTransactions').find('row');
// Loop through the transaction div container
// Find your model properties from fields
var transactions = [];
// Fill transaction related information in the array
// e.g. Find Amount's value and other properties in a Row with in the loop
var transaction = {
'Amount': Amount,
'TransDateTime': TransDateTime,
'Location': Location,
'Desc1': Desc1
}
transactions.push(transaction);
// user your actual post url here
// Data would be automatically deserialized to the model i.e. AcctCardTransaction
var jqreq = $.post('/Prepaid',
{
'LastFourAcctNumber': lastFourAccNo,
'LastFourDigCard': lastFourDigCard,
'Description': description,
'AssociatedTransactions': transactions
});
jqxhrjqreq.done(function (data) {
if (data === true) {
alert('Success!!');
} else {
onError(null);
}
});
jqreq.fail(function (e) {
onError(e);
});
}
return false;
});
i'm using razor's listboxfor for the first time, but my Model is always null.
after reading similar posts and tryouts it still won't work.
Person.cshtml
#model SampleApp.Web.ViewModel.PersonViewModel
#{
ViewBag.Title = "Welcome";
}
<article>
<p>
Welcome to example page.
</p>
<p>
<div class="container">
//Post data works as expected, controllers create method write to db successfully
#using (Html.BeginForm("Create", "Person", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Personen</legend>
<div class="editor-label">
#* #Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Age)
#Html.ValidationMessageFor(model => model.Age)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Surrname)
</div>
</fielset>
</div>
<p>
<input type="submit" value="Create" />
</p>
}
//binding to Model fails, Model is null. Not be able to debug anything in controller action, it stops when "loading" the page
#using (Html.BeginForm("GetListBoxData", "Person"))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.ListBoxFor(model => model.ListboxData, Model.ListboxData);
}
</div>
PersonController.cs
[AcceptVerbs(HttpVerbs.Get)]
[ValidateAntiForgeryToken]
public ActionResult GetListBoxData()
{
var data = new List<PersonViewModel>();
data.Add(new PersonViewModel{Name = "Test", Surrname="testsurrname", Age=30});
var viewModel = new PersonViewModel()
{
ListboxData = data.AsEnumerable().Select(s=> new SelectListItem{Value=s.Name ,Text = s.Surrname}),
};
return View(viewModel);
}
[AcceptVerbs(HttpVerbs.Post)]
[ValidateAntiForgeryToken]
public ActionResult GetListBoxData(PersonViewModel persondata)
{
//TODO: handle values from View
return View(this);
}
[ValidateAntiForgeryToken]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Include = "Name, Surrname, Age")] PersonViewModel persondata)
{
try
{
PersonService personDataProvider = new PersonService();
personDataProvider.SavePerson(persondata);
return new RedirectResult("SomewhereToGo");
}
catch (DataException ex)
{
//TODO: Log
}
return View(this);
}
PersonViewModel
public class PersonViewModel
{
public int PersonId{ get; set; }
public int Age { get; set; }
public string Name { get; set; }
public string Surrname { get; set; }
public IEnumerable<SelectListItem> ListboxData { get; set; }
}
writing values from editFor to db works as expected without code for listboxfor.
after adding it to my html it should be filled from db on page loading, but I get a ReferenceNotSet Exception on page loading. Model.ListboxData is null, before GetListBoxData action is called.
Thanks a lot for your help!
Your form should submit the data via POST, not GET. And, you don't need to use enctype = "multipart/form-data", unless you want to upload files through your from.
You need two Index Actions in your Controller, one is for sending the data from your Controller to the View, and the other one is for getting the data back from the View, when the form is submitted (POST) to the server.
The first argument you pass to your ListBox (the expression) refers to the Property in your Model that the selected item from your ListBox will be stored in, which in this case is PersonId.
So, your View should look like this:
#model MVCApplication.Web.ViewModel.PersonViewModel
#using (Html.BeginForm("Index", "Person"))
{
#Html.ListBoxFor(model => model.PersonId, Model.ListBoxData)
<input type="submit" value="Save" />
}
Then, in your Controller, you'll have two Actions like this:
public ActionResult Index()
{
var viewModel = new PersonViewModel()
{
ListboxData = data.Select(s => new SelectListItem { Value = s.PersonId.ToString(), Text = s.PersonId.ToString() }).AsEnumerable();
};
return View(viewModel);
}
[HttpPost]
public ActionResult Index(PersonViewModel viewModel)
{
// code to save the data in the database or whatever you want to do with the data coming from the View
}
By the way, in your ViewModel, you don't have to define your ListBoxData property like that, just do this:
public class PersonViewModel
{
public int PersonId{ get; set; }
public IEnumerable<SelectListItem> ListBoxData { get; set; }
}