What is wrong with the following code? It was generated by teh add view wizard. And when I navigate to the controller I get the following error: String was not recognised as a valid Boolean and the following line is highlighted: #using (Html.BeginForm())
Here is the view:
#model Radio_Management_Interface.DomainModel.Entities.Network
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout_main.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Network</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">
#Html.LabelFor(model => model.startCode, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.startCode)
#Html.ValidationMessageFor(model => model.startCode)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.frequency, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.frequency)
#Html.ValidationMessageFor(model => model.frequency)
</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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}`
Controller:
//
// GET: /Networks/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Network network = db.Networks.Find(id);
if (network == null)
{
return HttpNotFound();
}
return View(network);
}
Domain Model:
public class Network
{
public int networkID { get; set; }
public string name { get; set; }
public int startCode { get; set; }
public decimal frequency { get; set; }
public virtual List<Block> blocks { get; set; }
}
Your id is a nullable type, replace it with this line instead:
Network network = db.Networks.Find(id.Value);
And this:
if (id == null)
Can be changed to this:
if (!id.HasValue)
The problem will be with the following line:
Network network = db.Networks.Find(id);
The id is actually a nullable type that is passed to your Find method when it is expecting the value.
With nullable types you can read the underlying value with the Value property i.e.
id.Value
Related
This is my view.
I'm starting with MVC C#.
Sorry if this is an a very easy question.
I'm trying to get a CheckBox value from the view. The idea is put some checkboxes on the view, convert these values to Int32, to concatenate on a string entity for afterlly save in my DB.
The checkboxes should not be linked to the model.
Could someone explain me how to do it and how to link the checkbox to the controller? I'm very confused.
This is my model.
namespace Crossdock.Models{
public class Roles
{
[Key]
[Column(Order = 0)]
public int RolID { get; set; }
[Display(Name = "Tipo de Usuario")]
public string Descripcion { get; set; }
[Display(Name = "Permisos")]
public string Permisos { get;set;}
//Permisos a validar por Área
//Guías
public bool GeneracionGuias { get; set; }
//CEDIS
public bool RecepcionPaquetes { get; set; }
public bool CrossdockTemporal { get; set; }
//Administración
public bool Catalogos { get; set; }
}
}
This is my controller code. Here is where i need parse the bool values from the model to int/string and concatenate for save on "Descripcion" string field.
// GET: Roles/Create
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Roles cl)
{
if (!ModelState.IsValid)
{
return RedirectToAction("Index");
}
var rl = new Roles
{
RolID = 0,
Descripcion=cl.Descripcion,
Permisos=cl.Permisos,
};
objRol.Alta_Roles(rl);
return RedirectToAction("Index", new { area = "" });
}
This is my Create View.
#model Crossdock.Models.Roles
#{
ViewBag.Title = "Create";
}
<hr />
<h1>Registrar Nuevo Perfil de Permisos</h1>
<hr />
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Descripcion, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Descripcion, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Descripcion, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Permisos, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Permisos, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Permisos, "", new { #class = "text-danger" })
</div>
</div>
<br />
<div class="container">
<div class="row justify-content-center">
<div class="col-4">
<h3>
Guías
</h3>
<span> | Generación de Guías: </span> #Html.CheckBoxFor(m => m.GeneracionGuias, true)
</div>
<div class="col-4">
<h3>
CEDIS
</h3>
<span> | Recepción de Paquetes: </span> #Html.CheckBoxFor(m => m.RecepcionPaquetes, false)
<br />
<span> | Crossdock Temporal: </span> #Html.CheckBoxFor(m => m.CrossdockTemporal, false)
</div>
<div class="col-4">
<h3>
Administración
</h3>
<span> | Catálogos: </span> #Html.CheckBoxFor(m => m.Catalogos, false)
</div>
</div>
</div>
<hr />
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Registrar" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
<br />
#Html.ActionLink("Regresar", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Found a solution, but a very ugly one, see at the bottom, can someone improve that solution?
So I have a dummy Model like this one
public class TestModel
{
public int TestModelID { get; set; }
public string Name { get; set; }
}
And another one like this one
public class Collector
{
public int CollectorID { get; set; }
public string CollectorString { get; set; }
public ICollection<TestModel> MyList { get; set; }
}
I would like to (in simple CRUD style) create a new object Collector and populate (later with dynamic addition of new fields, for now only one) the ICollection.
This is my view
#model TestApplication.Models.Collector
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Collector</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.CollectorString, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.CollectorString, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.CollectorString, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => Model.MyList.ToList()[0].Name)
<div class="col-md-10">
#Html.EditorFor(model => model.MyList.ToList()[0].Name, new { htmlAttributes = new { #class = "form-control" } })
</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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
And the controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Collector collector)
{
if (ModelState.IsValid)
{
db.Collectors.Add(collector);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(collector);
}
This is the resulting HTML code (only relevant part I hope)
<div class="form-group">
<label for="">Name</label>
<div class="col-md-10">
<input class="form-control text-box single-line" name="[0].Name" type="text" value="" />
</div>
</div>
However, the MyList in the controller when creating is always null, why? (Yes I know Haackeds Blog entry, still can't figure out why it doesn't work)
So the problem is, that this line
#Html.EditorFor(model => model.MyList.ToList()[0].Name, new { htmlAttributes = new { #class = "form-control" } })
although very recommended to use in MVC, generates this here
<input class="form-control text-box single-line" name="[0].Name" type="text" value="" />
which is obviously not working. How do I get razor to change [0].Name to MyList[0].Name?
**Update: **
So I found a solution, if a hard-code this here
<input class="form-control text-box single-line" name="MyList[0].Name" type="text" value="" />
The controller understands it and I don't get null. How to solve it using razor?
ICollection<T> does not have an indexer. IList<T> does
public class Collector {
public Collector() {
MyList = new List<TestModel>();
}
public int CollectorID { get; set; }
public string CollectorString { get; set; }
public IList<TestModel> MyList { get; set; }
}
This would allow
#Html.EditorFor(model => model.MyList[0].Name, new { htmlAttributes = new { #class = "form-control" } })
in the view to generate the desired markup
<input class="form-control text-box single-line" name="MyList[0].Name" type="text" value="" />
Which can also be used in a loop for multiple items
<div class="form-group">
#for(int i = 0; i < Model.MyList.Count; i++) {
#Html.LabelFor(model => Model.MyList[i].Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MyList.ToList()[i].Name, new { htmlAttributes = new { #class = "form-control" } })
</div>
}
</div>
When returning the model from the controllers initial call, just make sure that calls to the model's collection index has an item.
[HttpGet]
public ActionResult Create() {
var model = new Collector();
model.MyList.Add(new TestModel());
return View(model);
}
Try changing your collector class to include initialization.
public class Collector
{
public Collector()
{
set MyList = new Collection<TestModel>();
}
public int CollectorID { get; set; }
public string CollectorString { get; set; }
public ICollection<TestModel> MyList { get; set; }
}
You can do by this using razor syntax
<div class="form-group">
#for(int i = 0; i < Model.MyList.Count; i++) {
#Html.LabelFor(model => Model.MyList[i].Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.MyList[i].Name, new { htmlAttributes = new { #class = "form-control" } })
</div>
}
</div>
This question already has answers here:
Asp.Net MVC: Why is my view passing NULL models back to my controller?
(2 answers)
Closed 5 years ago.
I'm trying to send a form to ActionResult method but it is null always. In fact, I got the error Value cannot be null. but I don't know why I got it the error.
Here is ActionResult code and my view.
public class VocabularyController : Controller
{
private VocabContext _context;
public VocabularyController()
{
_context = new VocabContext();
}
// GET: Vocabulary
[Route("New")]
public ActionResult New()
{
return View();
}
[HttpPost]
public ActionResult Save(Vocabulary word)
{
if (ModelState.IsValid)
{
_context.Vocabularies.Add(word);
_context.SaveChanges();
}
return RedirectToAction("dashboard", "Home");
}
}
==============================
#model EnglishTest.Models.Vocabulary
#{
ViewBag.Title = "New";
}
<div class="row">
<div class="col-lg-12">
<div class="element-wrapper">
<h6 class="element-header">New Word Form</h6>
<div class="element-box">
#using (Html.BeginForm("Save", "Vocabulary", FormMethod.Post))
{
<div class="form-group">
#Html.LabelFor(m => m.Word)
#Html.TextAreaFor(m => m.Word, new { #class = "form-control", #placeholder = "Word" })
#Html.ValidationMessageFor(m => m.Word)
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
#Html.LabelFor(m => m.Defination)
#Html.TextAreaFor(m => m.Defination, new { #class = "form-control", #placeholder = "Definition" })
#Html.ValidationMessageFor(m => m.Defination)
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
#Html.LabelFor(m => m.Synonym)
#Html.TextAreaFor(m => m.Synonym, new { #class = "form-control", #placeholder = "Synonym" })
#Html.ValidationMessageFor(m => m.Synonym)
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
#Html.LabelFor(m => m.PersianTranslate)
#Html.TextAreaFor(m => m.PersianTranslate, new { #class = "form-control", #placeholder = "Persian Translation" })
#Html.ValidationMessageFor(m => m.PersianTranslate)
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
#Html.LabelFor(m => m.Examples)
#Html.TextAreaFor(m => m.Examples, new { #class = "form-control", #placeholder = "Examples" })
#Html.ValidationMessageFor(m => m.Examples)
</div>
</div>
</div>
#Html.HiddenFor(m => m.Id)
<div class="form-buttons-w"><button class="btn btn-primary" type="submit"> Save</button></div>
}
</div>
</div>
</div>
</div></div>
==============================
public class Vocabulary
{
public int Id { get; set; }
[Required]
public string Word { get; set; }
[Required]
public string Defination { get; set; }
[Required]
public string Synonym { get; set; }
[Required]
public string PersianTranslate { get; set; }
[Required]
public string Examples { get; set; }
}
I Changed the input parameter to my model name, it works fine.
public ActionResult Save(Vocabulary vocabulary)
Specify a post to the form:
#using (Html.BeginForm("Save", "Vocabulary", FormMethod.Post))
Also the second # is not requried:
Html.BeginForm("Save", "Vocabulary", FormMethod.Post)
This question already has answers here:
Asp.Net MVC: Why is my view passing NULL models back to my controller?
(2 answers)
Closed 6 years ago.
In my MVC application, I have a model class like below
public class PROJECT
{
[Display(Name = "Project No.")]
public string PROJECT_NO { get; set; }
[Display(Name = "Title")]
[DataType(DataType.MultilineText)]
[Required]
public string TITLE { get; set; }
[Display(Name = "Description")]
[DataType(DataType.MultilineText)]
public string DESCRIPTION { get; set; }
[Display(Name = "Remarks")]
public string REMARKS { get; set; }
}
And I have a ViewModel like this
public class ProjectViewModel
{
public PROJECT Project { get; set; }
public bool IsSelected { get; set; }
public COMPANY Companies { get; set; }
public CLIENT Clients { get; set; }
}
The ViewModel is the one I am creating the controller and views for. I have created the Index, Details, Delete and Create Views as well. Index, Details and Delete Views just work fine but Create controller model binding does not seem to be working. The ProjectViewModel object that comes in as input to the controller Create is null. How do I bind the ViewModel as a parameter to this object?
// POST: /Project/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ProjectViewModel project)
{
if (ModelState.IsValid)
{
db.PROJECTs.Add(project.Project);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CLIENT_ID = new SelectList(db.CLIENTs, "ID", "NAME", project.Project.CLIENT_ID);
ViewBag.COMPANY_ID = new SelectList(db.COMPANies, "ID", "NAME", project.Project.COMPANY_ID);
return View(project);
}
And here is the Create View
#model IMCCBluePrints.Models.ProjectViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>PROJECT</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Project.PROJECT_NO, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Project.PROJECT_NO)
#Html.ValidationMessageFor(model => model.Project.PROJECT_NO)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Project.TITLE, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Project.TITLE)
#Html.ValidationMessageFor(model => model.Project.TITLE)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Project.DESCRIPTION, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Project.DESCRIPTION)
#Html.ValidationMessageFor(model => model.Project.DESCRIPTION)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Project.REMARKS, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Project.REMARKS)
#Html.ValidationMessageFor(model => model.Project.REMARKS)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Project.COMPANY_ID, "COMPANY_ID", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("COMPANY_ID", String.Empty)
#Html.ValidationMessageFor(model => model.Project.COMPANY_ID)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Project.CLIENT_ID, "CLIENT_ID", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("CLIENT_ID", String.Empty)
#Html.ValidationMessageFor(model => model.Project.CLIENT_ID)
</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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
In your GET action instantiate your project class and try:
...
ProjectViewModel.project = new PROJECT();
...
return View(ProjectViewModel);
The Issue that when form submit project conflict with type Project as it is complex type, Just rename it to be model for example
public ActionResult Create(ProjectViewModel model)
try this and it will work, i've tried by myself.
I have a web application with this controller:
public class ServiceRequestController : Controller
{
[Authorize(Roles = "Customer")]
public ActionResult Create()
{
return View();
}
[Authorize(Roles = "Customer")]
public ActionResult CreateNewUserAccount()
{
return View();
}
[Authorize(Roles = "Customer")]
[HttpPost]
public ActionResult CreateNewUserAccount(ServiceRequest serviceRequest)
{
if (ModelState.IsValid)
{
serviceRequest.Log.Id = User.Identity.GetUserId().ToString();
serviceRequest.Log.DateTimeLogged = System.DateTime.Now;
serviceRequest.LogID = db.Logs.Max(item => item.LogID);
serviceRequest.EstimatedResolveDate serviceRequest.CalculateEstimatedResolveDate();
db.ServiceRequests.Add(serviceRequest);
db.SaveChanges();
return RedirectToAction("AllServiceRequests", "Log");
}
return View(serviceRequest);
}
The serviceRequest.Log.Id = User.Identity.GetUserId().ToString(); (And any preceding line if this is commented out) throws a null reference exception. I presume the serviceRequest is somehow null?
The ActionLink which requests the CreateNewUserAccount() page is:
#Html.ActionLink("New User Account", "CreateNewUserAccount", "ServiceRequest")
I'm not sure how to resolve this exception?
The model is:
public partial class ServiceRequest
{
public int ServiceRequestID { get; set; }
public Nullable<int> LogID { get; set; }
public string RequestType { get; set; }
[DisplayName("Additional Information")]
[Required]
[StringLength(200)]
public string AdditionalInformation { get; set; }
public DateTime EstimatedResolveDate { get; set; }
[Required]
[DisplayName("Delivery Date")]
public DateTime DeliveryDate { get; set; }
public virtual Log Log { get; set; }
public DateTime CalculateEstimatedResolveDate()
{
return System.DateTime.Now.AddDays(3);
}
}
View code:
#model OfficiumWebApp.Models.ServiceRequest
#{
ViewBag.Title = "New User Account";
}
#using(Html.BeginForm("CreateNewUserAccount", "ServiceRequest", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.RequestType, new { #class = "control-label col-md-2" })
<div class="col-md-3">
<div class="editor-field">
#Html.TextBoxFor(model => model.RequestType, new { #Value = ViewBag.Title, #readonly = "readonly" })
#Html.ValidationMessageFor(model => model.RequestType)
</div>
</div>
</div>
<div class="form-group">
#Html.Label("Name of Account Holder", new { #class = "control-label col-md-2" })
<div class="col-md-3">
<div class="editor-field">
#Html.TextBox("AccountName")
#Html.ValidationMessageFor(model => model.RequestType)
</div>
</div>
</div>
<div class="form-group">
#Html.Label("Department", new { #class = "control-label col-md-2" })
<div class="col-md-3">
<div class="editor-field">
#Html.TextBox("Department")
#Html.ValidationMessageFor(model => model.RequestType)
</div>
</div>
</div>
<div class="form-group">
#Html.Label("Location", new { #class = "control-label col-md-2" })
<div class="col-md-3">
<div class="editor-field">
#Html.TextBox("Location", null, new { id = "Location" }))
#Html.ValidationMessageFor(model => model.RequestType)
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AdditionalInformation, new { #class = "control-label col-md-2" })
<div class="tags">
<div class="col-md-10">
#Html.TextAreaFor(model => model.AdditionalInformation)
#Html.ValidationMessageFor(model => model.AdditionalInformation)
</div>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DeliveryDate, new { #id = "VisitDateLabel", #class = "control-label col-md-2" })
<div class="col-md-3">
<div class="editor-field">
#Html.JQueryUI().DatepickerFor(model => model.DeliveryDate).Inline(false)
#Html.ValidationMessageFor(model => model.DeliveryDate)
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-floppy-save"></span></button>
</div>
</div>
</div>
}
You need to return the view i.e.
[Authorize(Roles = "Customer")]
public ActionResult CreateNewUserAccount()
{
var model = new ServiceRequest();
model.Log = new Log();
return View(model);
}
In your view you need to add a model reference too at the top i.e.
#model ServiceRequest
You could also initialise the Log object in your model as follows:
public class ServiceRequest
{
public ServiceRequest()
{
Log = new Log();
}
....
}
An action link will not post your model back, you need to include it within a form and include all the model values that you want to be updated on the client i.e.
#using (Html.BeginForm("CreateNewUserAccount", "ServiceRequest", FormMethod.Post)){
#Html.EditorFor(m => m.AdditionalInformation)
...
<input type="submit" value="submit" />
Update
Taken from the below comments, this was resolved by creating a new log on post i.e.
var log = new Log {
Id = User.Identity.GetUserId().ToString(),
DateTimeLogged = System.DateTime.Now,
LogID = db.Logs.Max(item => item.LogID) };
serviceRequest.Log = log;