How MVC creates c# class from html form? - c#

we have some c# model
public class PartnerRegistrationForm
{
public string Name { get; set; }
public string Company { get; set; }
public string Email { get; set; }
}
class that contains this model
public class PartnerRegistrationFormHolder
{
public PartnerRegistrationForm PartnerRegistrationForm { get; set; }
}
view
#model WebApplication1.Models.PartnerRegistrationFormHolder
#using (Html.BeginForm("Index", "Registration", FormMethod.Post))
{
#Html.TextBoxFor(e => e.PartnerRegistrationForm.Name)
#Html.TextBoxFor(e => e.PartnerRegistrationForm.Email)
#Html.TextBoxFor(e => e.PartnerRegistrationForm.Company)
<button type="submit">Send</button>
}
this method TextBoxFor create inputs with long names like 'PartnerRegistrationForm.Company'
ok, its reflection magic
then i fill this form and submit it
i have view
[HttpPost]
public ActionResult Index(PartnerRegistrationFormHolder partnerRegistrationFormHolder)
{
return new HttpNotFoundResult();
}
i run my program with debug and take a breakpoint on this action
HOW MVC create object from form? can anyone explain me or give me some link where to read?

more reflection magic :) it's called model binding:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-2.1

Related

Accessing model value for if statement

I'm new to MVC and I'm trying to make an if statement in the controller that accesses a value from my model. For example, if I am trying to access this radio button value from my model, how would I do it?
[Required] public bool radbutton { get; set; }.
At the top, I tried 'using PasswordTool.Models'.
Then inside my method:
if(PasswordModel.radbutton)
//do something
PasswordModel
namespace PasswordTool.Models
{
public class PasswordModel
{
[Required] public string Password { get; set; }
[Required] public bool RadioButton { get; set; }
}
}
I expect the PasswordModel.radbutton to access the value of the radio button in the model, but intellisense isn't even registering that it exists.
Hi there heisenberg3481,
Welcome to StackOverflow!
To pass Model values from the View you would need to do the following:
#model PasswordModel
// - If the bellow doesn't work try removing the 'Controller' in "MemberController" - //
#using (Html.BeginForm("GetPassword", "MemberController"))
{
Html.TextBoxFor(x => x.Password);
Html.RadioButtonFor(x => x.RadioButton);
<button type="submit">
Submit
</button>
}
Then in your controller you can retrieve the data like so:
[HttpPost]
public ActionResult GetPassword (PasswordModel objModel)
{
if (objModel.RadioButton) {
// Execute action
}
return View();
}

In MVC, how do I create a view that will update a parent model, and all children models?

I'm brand new to MVC, still trying to read and learn the ropes, and this question has come up.
If I had a model, let's say User, that looks like this:
public partial class User
{
public int ID { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public string Email { get; set; }
public virtual Child Child { get; set; }
}
And a model, Child, which is a child entity to the parent User:
public partial class Child
{
public int ID { get; set;}
public string Name { get; set; }
public virtual Toy Toy { get; set; }
}
And a final model, Toy, which is a child model to the parent model Child:
public partial class Toy
{
public int ID { get; set; }
public string ToyName { get; set; }
}
And I wanted to create a View that would have fields available for all of them, how would I write the controller/view so that if all the fields were filled it would create the records correctly? So that the ToyName would be for the appropriate Toy, which would be for the appropriate Child, which would be for the appropriate User?
This is just an example I was thinking of, because I wanted to try to make a sort of pet project to practice MVC, and I can't seem to find many sources explaining how to do this.
you will have to scaffolding your user ViewModel. This will allow you to fetch User -> Child -> Toy data.
https://blogs.msdn.microsoft.com/mcsuksoldev/2013/09/20/managing-entity-relationships-with-mvc-scaffolding/
You will probably had to use Viewmodels to fetch all the data from all those different tables. Check on them.
It's really straight forward.
A minimalist example.
The View EditUser.cshtml:
#model WebApplication2.Models.User
#using (Html.BeginForm("SaveUser", "Home", FormMethod.Get))
{
#Html.LabelFor(m => m.Username)
#Html.EditorFor(m => m.Username) <br />
#Html.LabelFor(m => m.Child.Name)
#Html.EditorFor(m => m.Child.Name) <br/>
#Html.LabelFor(m => m.Child.Toy.ToyName)
#Html.EditorFor(m => m.Child.Toy.ToyName) <br />
<input type="submit" />
}
The action methods in the Home controller:
public ActionResult EditUser(User user)
{
return View(user);
}
public ActionResult SaveUser(User user)
{
// Do something with user to save it
// then show the Edit form again
return View("EditUser", user);
}

Form submission in partial views in MVC

I am developing a simple mvc application . The code is as follows:
Model .cs:
public class CustomModel
{
public IEnumerable<lang> lstlang { get; set; }
public IEnumerable<org> lstOrg { get; set; }
}
public class lang
{
public int langid { get; set; }
public string langName { get; set; }
}
public class org
{
public int orgId { get ;set;}
public string orgName { get; set; }
}
Controller.cs
public Action Index()
{
// Get data from database and fill the model
var model = new CustomModel();
return View(model);
}
public Action Partial()
{
// Get data from database and fill the model
var model = new CustomModel();
return PartialView(model);
}
[HttpPost]
public Action Partial(FormCollection frm, CustomModel model)
{
// Get data from database and fill the model
var model = new CustomModel();
return PartialView(model);
}
Index.cshtml
#model CustomModel
#Html.TextboxFor(x => x.lang.FirstOrDefault().id);
<input type="button" id="btn" />
#Html.RenderPartial("Partial", model)
Partial.cshtml
#model CustomModel
#Html.TextboxFor(x => x.lang.FirstOrDefault().id);
<input type="submit" id="submit" />
The thing is, when I click the submit button in the Partial.cshtml page, and examine the model in httppost method in public Action Partial(FormCollection frm, CustomModel model), the model contains null for both lists lstlang and lstOrg, but the formcollection[0] will give the selected textbox value.
What am I missing, or is this the right way of using partial views?
Don't use FirstOrDefault(). If you want to post something back to the front end with collections, you'll need to use indexing.
Public class CustomModel
{
public ICollection<lang> lstlang { get; set; }
public ICollection<org> lstOrg { get; set; }
}
#HTML.textboxfor(x=>x.lang[0].id);

Model properties are null when the form is submitted

On an ASP.NET MVC 5 project I have the following model:
public class ScheduleIndexModel {
public IPageList<DataModel> Data { get; set; }
public FormModel Form { get; set; }
public class DataModel {
public Int32 Id { get; set; }
public String[] Attendees { get; set; }
public String Location { get; set; }
public DateTime Date { get; set; }
} // DataModel
public class FormModel {
public String Location { get; set; }
public String Date { get; set; }
} // FormModel
}
The view is the following:
<form action="#Url.Action(MVC.Schedule.Index())" method="post">
#Html.LabelFor(x => x.Form.Date, "Date")
#Html.TextBoxFor(x => x.Form.Date)
#Html.LabelFor(x => x.Form.Location, "Location")
#Html.TextBoxFor(x => x.Form.Location)
#Html.SubmitButton("Filter", "Index", new { #class = "submit" })
#Html.AntiForgeryToken()
</form>
Then the HTTPPost controller action is as follows:
[HttpPost]
public virtual ActionResult Index(ScheduleIndexModel.FormModel model, Int32 p = 1) {
return View();
} // Index
When I submit the form the model is not null but its properties are even if I write something on the TextBoxes.
Does anyone knows what am I doing wrong?
You may need to use a binding prefix because your viewmodel is nested. Something like this may work:
public virtual ActionResult Index([Bind(Prefix = "Form")] FormModel model)
Your html helpers (e.g. #Html.TextBoxFor(x => x.Form.Date) will be generating html like this
<input name="Form.Date" .../>
but because your post method accepts parameter of type FormModel it cant match up (FormModel only has property Date, not property Form that has property Date).
You can either change you action method to
public virtual ActionResult Index(ScheduleIndexModel model,...
{
FormModel form = model.Form; // get the FormModel
or use the [Bind(Prefix..)] as suggested by Big Daddy

Can't get all my ViewModel properties back after the postback -MVC Partial Views

Can't get all my ViewModel properties back after the postback (After user entered some values on HttpPost)
There are numerous questions here related to losing data or getting nulls after the postback
I tried some of them and played around on my case, I think the scenario is a bit different,
Using a PartialView or Editor Templates(except a list property), Always the returned result properties are null.
In partialView approach always all the properties are null, I think maybe I missed a piece.
In the "custom editor template approach for the type", I'll have just "EnteredNums" List returned. (Maybe because these are what the template have EditorFor for them, but what is the solution here if that's the case?)
Don't know weather if it's important here or not, the application also uses Unity. I don't think it be the problem here.
The HttpGet Passed model is the same as HttpPost : DataVm
The name of the action is also the same : ProcessEnteredData
=================== Controller and action
[HttpPost]
public ActionResult ProcessEnteredData(DataVm vm)
{
if (ModelState.IsValid)
{
foreach (NumType num in vm.EnteredNums)
{
int i1 = num.Score1;
int i2 = num.Score2;
string profTitle = vm.Profile.Title;
Repository.Context.EnteredNums.Add(num);
}
return RedirectToAction("ShowTable");
}
else
{
return View(vm);
}
}
==============
The Partial View of Custom Editor Template are similar :
#model xxxx.NumType
#Html.LabelFor(m => m.TheTitle)
#Html.TextBoxFor(m => m.Score1)
#Html.TextBoxFor(m => m.Score2)
#Html.HiddenFor(m => m.Profile)
// Profile or ProfileId - Just used to see could it bring the property back or not as a test
============
NumType Model
[Key]
public int NumTypeId { get; set; }
[ForeignKey("Profile")]
[Required]
public int ProfileId { get; set; }
public int Score1 { get; set; }
public int Score2 { get; set; }
public int BoxId { get; set; }
public Box Box { get; set; } // something not important here
public virtual Profile Profile { get; set; }
============
The ViewModel
public class DataVm
{
public Profile Profile { get; set; }
public string TheTitle { get; set; }
public List<NumType> EnteredNums { get; set; }
// In the Editor template approach it's the only item with data and others are null
public List<Box> Boxes { get; set; }
}
=========
View for PartialView approach :
#model xxxx.DataVm
#using (Html.BeginForm("ProcessEnteredData", "Profile", FormMethod.Post))
{
#Html.AntiForgeryToken()
Model.EnteredNums = new List<NumType>();
foreach(var box in Model.Boxes)
{
NumType num = new NumType();
num.Profile = Model.Profile;
num.Box = box;
int iCount = Model.EnteredNums.Count;
Model.EnteredNums.Add(num);
#Html.Partial("NumView", Model.EnteredNums[iCount]);
}
<input type="submit" value="Do Process" />
}
===================
View for Editor for approach :
// instead of #Html.Partial :
#Html.EditorFor(m => m.EnteredNums[iCount]);

Categories