EditorForModel shows nothing on the view - asp.net-mvc

The model is
public class AdminTicket
{
public int Id;
public string Title;
public string Description;
public DateTime CreationDate;
}
The action is
public ViewResult EditTicket(int id)
{
return View(_ticketRepository.Tickets.FirstOrDefault(c => c.Id == id));
}
(I checked, an action give to a view the right model)
The view is
#model TicketSystemMVC5.Models.AdminTicket
#using (Html.BeginForm("EditTicket", "Admin"))
{
#Html.EditorFor(model=>model.Title)
#Html.EditorForModel()
<input type="submit" value="Save" />
#Html.ActionLink("Вернуться к списку", "Index")
}
The result is a form with Title-editor, a button and a link. Where are all the editor fields?

The EditorForModel doesn't like fields, it only renders properties - you can use the "auto-properties" quite happily:
public class AdminTicket {
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime CreationDate { get; set; }
}
Then your input fields will magically appear.
This is as documented (emphasis added):
Returns an HTML input element for each property in the model.
To test, this I created the following class:
public class AdminTicket {
public int Id { get; set; }
public string Title;
public string Description;
public DateTime CreationDate { get; set; }
}
And EditorForModel resulted in:

Related

Posting data from single view to two model classes

I have created Viewmodel class and created two properities(by using two model classes i.e from customerModel & addressModel) in that class.Then how to bind the data from view to model.
namespace customer2.Models
{
public class customerdetails {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { set; get; }
[Key] public int customerid { set; get; }
public string customername { set; get; }
}
public class addressdetails
{
public int addressno { set; get; }
public string street { set; get; }
public string landmark { set; get; }
public int pincode { set; get; }
}
public class MkContext : DbContext
{
public virtual DbSet<customerdetails> customers { get; set; }
public virtual DbSet<addressdetails> address { get; set; }
}
public class customerviewmodel
{
public customerdetails cd { set; get; }
public List<addressdetails> ad { set; get; }
}
}
Create a ViewModel with Combined values of other two data Models for what values we are capture as input in Form
place the ViewModel as a parameter in the controller action method.
Inside the action method, you can bind the values to the two different data models.
HTML Form
<form action='controller/SaveCustomer' method='post'>
<input Type='text' name='FirstName' />
<input Type='text' name='LastName' />
<input Type='text' name='Address' />
</form>
View Model
Public Class CustViewModel {
public string FirstName {get; set;}
public string LastName{get; set;}
public string Address{get; set;}
}
Customer Data Model
Public Class CustModel {
public string FirstName {get; set;}
public string LastName{get; set;}
}
addressModel
Public Class AddModel {
public string Address{get; set;}
}
Controller Method
Public ActionResult SaveCustomer(CustViewModel Details)
{
CustModel Cust = new CustModel();
AddModel Add= new AddModel();
Cust.FirstName= Details.FirstName;
Cust.LastName = Details.LastName;
Add.Address = Details.Address ;
return view();
}
Or Else You Can directly add the model class in Controller
Controller Method
Public ActionResult SaveCustomer(CustModel CustDetails, AddModel AddDetails)
{
//Do the Action
return view();
}

knockout 3 level mapping, 3rd level doesnt change

I am new to KnockoutJS and I am trying to create a 3-level model binding, for a master-detail ASP.NET MVC view.
here is the screen i am trying to implement this behavior on:
I have the following ViewModel design
public class CreateReservationViewModel
{
public string Title { get; set; }
public String LogoPath { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public int TimeSpan { get; set; }
public int MinPersons { get; set; }
public int MaxPersons { get; set; }
public List<ReservationOptionViewModel> ReservationOptions { get; set; }
public string MessageToClient { get; set; }
public CreateReservationViewModel()
{
ReservationOptions = new List<ReservationOptionViewModel>();
}
}
public class ReservationOptionViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public int TypeId { get; set; }
public string TypeDescription { get; set; }
public string Info { get; set; }
public List<ValuesViewModel> ReservationOptionValues { get; set; }
public ReservationOptionViewModel()
{
ReservationOptionValues = new List<ValuesViewModel>();
}
}
public class ValuesViewModel
{
public int Id { get; set; }
public string ValueTitle { get; set; } // this value i cant seem to get to bind user input always defaults to whatever i set it in knockout
}
and here is my .js and .html https://jsfiddle.net/camLpdty/
Although I am able to successfully bind the first and second levels, 3rd level binding always picks up default values i.e: [({ Id: 0, ValueTitle: "this is read only and cant change"})] }
everything else seems to work...
From your jsfiddle it looks like the binding context for the Values column is a bit off. data-bind="value: Values.ValueTitle" - Here Values is an array but you're trying to bind a single input box to it. It doesn't know which element's ValueTitle to use so it's probably not bound to anything. You'll need to use a "foreach" or change how you're displaying that information
As a quick test you can try changing that last binding from:
<td>
<input class="form-control input-sm"
data-bind="value: ReservationOptionValues.ValueTitle" />
</td>
to
<td data-bind="foreach: ReservationOptionValues">
<input class="form-control input-sm" data-bind="value: ValueTitle" />
</td>
This will create an input box for every element in the Values array so you probably don't want to leave it like this, but it should highlight the knockout-context problem

how post date.time value to model controller in mvc

I don't know how to pass DateTime value to my model from Html.BeginForm.
I don't want to use calender.
Can I use hidden field to pass it to model?
public partial class gpAdmin
{
public long Id { get; set; }
public string name { get; set; }
public System.DateTime registerDate { get; set; }
}
and view
#using (Html.BeginForm())
{
<div>
<div class="editor-label">
#Html.Label("Name")
#Html.TextBoxFor(a => a.name)
#Html.ValidationMessageFor(m => m.name)
</div>
......
}
and register controller
[HttpPost]
public ActionResult Index(gpAdmin admin)
{
if (ModelState.IsValid)
{
ds.gpAdmin.Add(admin);
ds.SaveChanges();
}
return view();
}
What should I do for the registerDate field, which is a DateTime type?
You may use #Html.EditorFor(a=>a.registerDate).
You may also consider adding attributes to the field
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public System.DateTime registerDate { get; set; }
If you want that to be hidden use #Html.HiddenFor(a=>a.registerDate)
But if you have to use #Html.HiddenFor I recommend not using it at all and initializing default date in the model constructor itself.. use the following code
public partial class gpAdmin
{
public gpAdmin()
{
registerDate = DateTime.Now;
}
public long Id { get; set; }
public string name { get; set; }
public System.DateTime registerDate { get; set; }
}

Model nested type is null when after modelbinding

I have a ViewModel as below:
public class CheckoutViewModel
{
public string ProductNumber { get; set; }
public string Name { get; set; }
public int Price { get; set; }
public Input UserInput;
public class Input
{
public string Email { get; set; }
public string Phone { get; set; }
}
}
And an action like this:
[HttpPost]
public ActionResult Index(CheckoutViewModel model)
{
// ...
return View();
}
And my model has bound as below:
#model GameUp.WebUI.ViewModels.CheckoutViewModel
#using (Html.BeginForm("Index", "Checkout", FormMethod.Post))
{
#Html.AntiForgeryToken()
<!-- some HTML -->
#Html.LabelFor(m => m.UserInput.Email)
#Html.TextBoxFor(m => m.UserInput.Email)
#Html.LabelFor(model => model.UserInput.Phone)
#Html.TextBoxFor(model => model.UserInput.Phone)
<button>Submit</button>
}
When I submit the form, the UserInput is null. I know ASP.NET MVC is able to bind nested types but in this code is not. Also I can get the Email and Phone values by:
var email = Request.Form["UserInput.Email"];
var phone = Request.Form["UserInput.Phone"];
Maybe I do something wrong! It's a simple model binding you can find everywhere in the web.
You forgot to put a setter in your UserInput, I don't think the setter is automatic. Anyway you can make it work by just putting a getter/setter in your UserInput and no need to do extra in your controller method:
public Input UserInput { get; set; }
Your complete model:
public class CheckoutViewModel
{
public string ProductNumber { get; set; }
public string Name { get; set; }
public int Price { get; set; }
public Input UserInput { get; set; }
public class Input
{
public string Email { get; set; }
public string Phone { get; set; }
}
}

DefaultModelBinder not binding nested model

Looks like others have had this problem but I can't seem to find a solution.
I have 2 Models: Person & BillingInfo:
public class Person
{
public string Name { get; set;}
public BillingInfo BillingInfo { get; set; }
}
public class BillingInfo
{
public string BillingName { get; set; }
}
And I'm trying to bind this straight into my Action using the DefaultModelBinder.
public ActionResult DoStuff(Person model)
{
// do stuff
}
However, while the Person.Name property is set, the BillingInfo is always null.
My post looks like this:
"Name=statichippo&BillingInfo.BillingName=statichippo"
Why is BillingInfo always null?
I had this problem, and the answer was staring me in the face for a few hours. I'm including it here because I was searching for nested models not binding and came to this answer.
Make sure that your nested model's properties, like any of your models that you want the binding to work for, have the correct accessors.
// Will not bind!
public string Address1;
public string Address2;
public string Address3;
public string Address4;
public string Address5;
// Will bind
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string Address4 { get; set; }
public string Address5 { get; set; }
Status no repro. Your problem is elsewhere and unable to determine where from what you've given as information. The default model binder works perfectly fine with nested classes. I've used it an infinity of times and it has always worked.
Model:
public class Person
{
public string Name { get; set; }
public BillingInfo BillingInfo { get; set; }
}
public class BillingInfo
{
public string BillingName { get; set; }
}
Controller:
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new Person
{
Name = "statichippo",
BillingInfo = new BillingInfo
{
BillingName = "statichippo"
}
};
return View(model);
}
[HttpPost]
public ActionResult Index(Person model)
{
return View(model);
}
}
View:
<% using (Html.BeginForm()) { %>
Name: <%: Html.EditorFor(x => x.Name) %>
<br/>
BillingName: <%: Html.EditorFor(x => x.BillingInfo.BillingName) %>
<input type="submit" value="OK" />
<% } %>
Posted values: Name=statichippo&BillingInfo.BillingName=statichippo is perfectly bound in the POST action. Same works with GET as well.
One possible case when this might not work is the following:
public ActionResult Index(Person billingInfo)
{
return View();
}
Notice how the action parameter is called billingInfo, same name as the BillingInfo property. Make sure this is not your case.
I had the same issue, the previous developer on the project had the property registered with a private setter as he wasn't using this viewmodel in a postback. Something like this:
public MyViewModel NestedModel { get; private set; }
changed to this:
public MyViewModel NestedModel { get; set; }
This is what worked for me.
I changed this:
[HttpPost]
public ActionResult Index(Person model)
{
return View(model);
}
To:
[HttpPost]
public ActionResult Index(FormCollection fc)
{
Person model = new Person();
model.BillingInfo.BillingName = fc["BillingInfo.BillingName"]
/// Add more lines to complete all properties of model as necessary.
return View(model);
}
public class MyNestedClass
{
public string Email { get; set; }
}
public class LoginModel
{
//If you name the property as 'xmodel'(other than 'model' then it is working ok.
public MyNestedClass xmodel {get; set;}
//If you name the property as 'model', then is not working
public MyNestedClass model {get; set;}
public string Test { get; set; }
}
I have had the similiar problem. I spent many hours and find the problem accidentally that I should not use 'model' for the property name
#Html.TextBoxFor(m => m.xmodel.Email) //This is OK
#Html.TextBoxFor(m => m.model.Email) //This is not OK

Resources