I'm working in a C# project. In my ReglasDispositivos view there are three diferent actions which a client can do: add a device, update a device and delete once. The controller calls ReglasDispositivos() (get) view passing a ClienteReglasDispositivos model. Lets go, for example, to adding a device. How can i post the info that the client is posting?
If my view only have one action, I know that I have to add in the controller [HttpPost] and [HttpGet] ReglasDispositivos() method. But when a view has three diferentes actions?
ClientController:
[HttpGet]
public ActionResult ReglasDispositivos()
{
ClienteReglasDispositivos model = new ClienteReglasDispositivos();
return View(model);
}
ReglasDispositivos view (Adding a device parte) (Im not sure about that BeginForm):
#model SistemaGestion.Models.ClienteReglasDispositivos
...
<div class="view-tables">
<div id="myAdd" class="div-table">
#using (Html.BeginForm("AgregarDispositivo", "Client", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
<fieldset class="fieldset-box">
<div class="editor-field">
#Html.TextBoxFor(model => model.NombreDispositivo, new { Class = "YourBackgroundClass", Placeholder = "Nombre del dispositivo" });
</div>
<div class="editor-field">
#Html.TextBoxFor(model => model.HorasDeUso, new { Class = "YourBackgroundClass", Placeholder = "KwPorHora" });
</div>
<div class="editor-field">
#Html.CheckBoxFor(model => model.EsInteligente, new { Class = "YourBackgroundClass" });
</div>
<input type="submit" class="submit-login" value="AGREGAR" />
</fieldset>
}
</div>
ClienteReglasDispositivos
public class ClienteReglasDispositivos
{
[Required]
public string NombreDispositivo { get; set; }
[Display(Name = "Es inteligente?")]
public bool EsInteligente { get; set; }
public double KwPorHora { get; set; }
public float HorasDeUso { get; set; }
public string Condicion { get; set; }
}
You can have multiple actions with identical name due to polymorphysm. Asp decide what action you call by [Http(XX)].
You can have
[HttpGet]
public ActionResult ReglasDispositivos()
{
ClienteReglasDispositivos model = new ClienteReglasDispositivos();
return View(model);
}
[HttpPost]
public ActionResult ReglasDispositivos([FromForm] ClienteReglasDispositivos model)
{
if(ModelState.IsValid(model)) {
//do something
}
return View(model);
}
Also you can call different action name and return same view
[HttpGet]
public ActionResult ReglasDispositivos()
{
ClienteReglasDispositivos model = new ClienteReglasDispositivos();
return View(model);
}
[HttpPost]
public ActionResult ReglasDispositivosPost([FromForm] ClienteReglasDispositivos model)
{
return View("ReglasDispositivos", model);
}
Read more
Related
I have a simple mvc5 code first application, It has a ms SQL database in the back-end and and a form in the front-end.
While I insert into database via the front end form, it does not generate any error, everything seems OK but when i check the back end database table, then all values in the newly inserted row are showing as NULL.
This is my code for model:
public class students
{
public int Id { get; set; }
[Display(Name = "Name")]
public string st_name { get; set; }
[Display(Name = "Father's Name")]
public string st_father_name { get; set; }
public string st_contact { get; set; }
}
This is the View Model class:
public class AddStudentViewModel
{
public students stdntss { get; set; }
}
This is the controller:
public ActionResult Index()
{
var std = _context.stdnts;
if (std==null)
{
return Content("Nothing Found");
}
return View(std);
}
public ActionResult AddStudent()
{
return View();
}
[HttpPost]
public ActionResult Insert(students st)
{
_context.stdnts.Add(st);
_context.SaveChanges();
return RedirectToAction("Index","Students");
}
And finally this is the view:
#model school2.ViewModels.AddStudentViewModel
#{
ViewBag.Title = "AddStudent";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>New student's registration form</h2>
#using (Html.BeginForm("Insert","Students"))
{
<div class="form-group">
#Html.LabelFor(m=> m.stdntss.st_name)
#Html.TextBoxFor(m=> m.stdntss.st_name, new { #class="form-control"})
</div>
<div class="form-group">
#Html.LabelFor(m => m.stdntss.st_father_name)
#Html.TextBoxFor(m => m.stdntss.st_father_name, new { #class = "form-control" })
</div>
<div class="form-group">
#Html.LabelFor(m => m.stdntss.st_contact)
#Html.TextBoxFor(m => m.stdntss.st_contact, new { #class = "form-control" })
</div>
<button type="submit" class="btn btn-primary">Save</button>
}
Kindly assist me if anyone has any clue?
One way to solve this is to change the POST method to accept the same model as the view.
try changing
public ActionResult Insert(students st)
{
_context.stdnts.Add(st);
_context.SaveChanges();
return RedirectToAction("Index","Students");
}
to
public ActionResult Insert(AddStudentViewModel st)
{
_context.stdnts.Add(st.stdntss );
_context.SaveChanges();
return RedirectToAction("Index","Students");
}
or changing the model of the form to simply be student.
I think that change #Html.TextBoxFor(model=> model.stdntss.st_name, new { #class="form-control"}). because call Model, #model school2.ViewModels.AddStudentViewModel . Variable default Model.
My ViewModel looks like this:
public class ProjectViewModel
{
public ICollection<Project> Projects { get; set; }
}
My controller:
[HttpPost]
[Route("ChooseProject")]
public ActionResult ChooseProject(Project projects)
{
return RedirectToAction("Index", "Application");
}
And finally my view:
#using ServicePortal.Web.Controllers
#model ServicePortal.Web.Models.ProjectViewModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Choose project";
}
<div class="pure-form pure-form-aligned">
#using (Html.BeginForm("ChooseProject", "Login", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="innerForm formgroup">
#Html.ValidationSummary(true, "", new { #class = "" })
#Html.DropDownListFor((model => model.Projects), new SelectList(Model.Projects,"ProjectKey", "ProjectName"))
<div class="row">
<button type="submit" class="button pull-right">Go on</button>,
</div>
</div>
}
</div>
The dropdownlist is populated with the correct values, but I would like to return either a Project or a string with ProjectKey to the controller. However, when I submit the form and check the value in the parameter in the controller, it is always null, both when I try to return a Project and when I try with string. I don't get any errors. What am I doing wrong?
Try this out:
public class ProjectViewModel
{
public string SelectedProjectKey { get; set; } // string may need to be int depending on what type ProjectKey is in your class
public ICollection<Project> Projects { get; set; }
}
In the view:
#Html.DropDownListFor((model => model.SelectedProjectKey), new SelectList(Model.Projects,"ProjectKey", "ProjectName"))
Your controller action:
public ActionResult ChooseProject(ProjectViewModel model)
This will get you the key of whatever project you selected in model.SelectedProjectKey and you can use that in your controller chooseproject action method to do whatever you intended.
I have ModelView which I have created for purpose to create new record instance via view-- razor form. In controller I need to assign list data to ViewModel; IEnumerable and then pass this model along with with list data (of CategoryType) which then in view I need to populate in drop-down list, followed by ID of selected CategoryType send back to controller along with other data.
I have assign IEnumerable value to model in controller but not sure is correct and how to do rest part in view ???
View Model - CompanyProfileModelView
public class CompanyProfileModelView
{
public Company _Company { get; set; }
public IEnumerable<CategoryType> _CategoryType { get; set; }
}
Model Class
public class CategoryType
{
public int CategoryTypeID { get; set; }
public string CategoryTitle { get; set; }
public ICollection<Company> Companies { get; set; }
}
Controller Class
[HttpGet]
public ActionResult CreateCompany()
{
var _listData = _appFunctions.GetAllCategory();
var _model = new CompanyProfileModelView
{
_CategoryType = _listData
??????????????
};
return PartialView("_CreateNewCompanyPartial", _model);
}
[HttpPost]
public ActionResult CreateCompany(CompanyProfileModelView _model)
{
try
{
if (ModelState.IsValid)
{
//my code will be here to read for input data
}
}
catch (DataException ex)
{
ModelState.AddModelError("", "Unable To Create New Function Navigation" + ex);
}
return RedirectToAction("Home");
}
View
#model App.DAL.Model.CompanyProfileModelView
#using (Html.BeginForm("CreateCompany", "CompanyProfile", FormMethod.Post, new { id = "NewFunctionNavigationForm" }))
{
<div class="form-group">
#Html.LabelFor(#model => #model._Company.CompanyName, new { #class = "control-label col-md-2" })
<div class="form-group">
#Html.EditorFor(#model =>#model._Company.CompanyName)
#Html.ValidationMessageFor(#model=>#model._Company.CompanyName)
</div>
</div>
<div class="form-group">
// need help here for dropdown of CategoryType list
</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>
}
Since DropDownList uses IEnumerable<SelectListItem>, change the view model to
public class CompanyProfileModelView
{
public Company Company { get; set; }
public SelectList CategoryList { get; set; }
}
and assuming Company model contains
[Display(Name="Category")]
public int? CategoryType { get; set; }
Controller
[HttpGet]
public ActionResult CreateCompany()
{
var listData = _appFunctions.GetAllCategory();
var model = new CompanyProfileModelView
{
CategoryList = new SelectList(listData, "CategoryTypeID ", "CategoryTitle")
};
return View(model);
}
[HttpPost]
public ActionResult CreateCompany(CompanyProfileModelView model)
{
if (!ModelState.IsValid)
{
// Re-assign select list if returning the view
var listData = _appFunctions.GetAllCategory();
model.CategoryList = new SelectList(listData, "CategoryTypeID ", "CategoryTitle");
return View(model)
}
// Save and redirect
}
View
#model App.DAL.Model.CompanyProfileModelView
#using (Html.BeginForm()) // Note, no parameters required in this case
{
....
#Html.LabelFor(m => m.Company.CategoryType, new { #class = "control-label col-md-2" })
#Html.DropDownListFor(m => m.Company.CategoryType, Model.CategoryList, "--Please select--")
#Html.ValidationMessageFor(m => m.Company.CategoryType)
.....
<input type="submit" value="Create" class="btn btn-default" />
}
I've got two models.
Model A for example contains basic get set for atrributes (i.e)
[Required]
[StringLength(100)]
[Display(Name = "Comment: ")]
public string Comment { get; set; }
public bool IsSuccess { get; set; }
Model two uses attributes in modal a, i.e
public ModelA Deposit { get; set; }
public ModelA Withdrawal { get; set; }
public ModelA Transfer { get; set; }
In my View all I am doing is using 3 forms in one page with very similar fields.
For same reason Withdrawal and transfer work with no problems. The code is almost identical in all 3
However when I am doing deposit, the ActionResult in the post is not been passed on the model.
public ActionResult Index()
{
SetViewBagAccounts();
var model = new ModelB {};
return View(model);
}
[HttpGet]
public ActionResult Deposit()
{
return View();
}
[HttpPost]
public ActionResult Deposit(ModelB model)
{
int acct = Convert.ToInt32(Request.Form["Accounts"]);
var comment = model.Deposit.Comment;// This causes **NullReferenceException**
}
The error I am getting in http post is NullReferenceExcption.
When I debug, the model being passed to the action method, Deposit, is all empty.
BELOW IS A SAMPLE OF THE VIEW
#model Login.Models.ModelB
#{
ViewBag.Title = "ATM";
}
<h2>ATM</h2>
<div id="leftpanel" style="position:absolute;left:0;width:33%;">
#using (Html.BeginForm("Deposit", "ATM", FormMethod.Post, new {}))
{
<div>
<fieldset>
<legend>Deposit Money</legend>
<div>#Html.LabelFor(u=>u.Deposit.AccountNumber1)</div>
<div>#Html.DropDownList("Accounts", "-- Select Account --")
</div>
<div>#Html.LabelFor(u=>u.Deposit.Amount)</div>
<div>#Html.TextBoxFor(u=>u.Deposit,new {style = "width:150px"})
#Html.ValidationMessageFor(u=>u.Deposit.Amount)
</div>
<div>#Html.LabelFor(u=>u.Deposit.Comment)</div>
<div>#Html.TextAreaFor(u=>u.Deposit.Comment,new {style = "width:250px"})
#Html.ValidationMessageFor(u=>u.Deposit.Comment)
</div>
<input type="submit" value ="Submit" style="width:31%;"/>
<input type="reset" value ="Clear" style="width:31%;"/>
</fieldset>
</div>
}
The div for deposit is pretty much copied again for withdrawal and transfer, only changed bit is :
#using (Html.BeginForm("Withdrawal", "ATM", FormMethod.Post, new {}))
#using (Html.BeginForm("Transfer", "ATM", FormMethod.Post, new {}))
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; }
}