NullReferenceException ASP.NET MVC 5 - c#

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;

Related

ASP.NET core all model values are null when passing a model to the view

Goal: I have a page that I want to have a return url passed through the model of the view so upon completion of the form, it will return to the previous url. The page is a address validation and add it to the account as a saved address.
Flow of the page: You are presented with an address form to fill out. on completion, you will have a button that will call to a controller method that will verify with FedEx via API, and then if valid, it will let you save the address.
Issue: once you press the Verify Address button, it seems to have an issue with sending the form data to the controller.
HTTPGET:
public ActionResult AddShippingAddress(string strReturnURL)
{
// get states
ViewBag.states = GetStates();
DeliveryAddressModel model = new DeliveryAddressModel();
model.strReturnAddress = strReturnURL;
return View(model);
}
AddShippingAddress.chshtml
#model EcommerceWebsite.Models.Home.DeliveryAddressModel
#{
ViewBag.Title = "Shipping Address";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<br />
<div class="container">
<partial id="ValidateAddress"></partial>
#using (Html.BeginForm())
{
<h4>Shipping Address</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
<h5>Name</h5>
<div class="col-md-10">
#Html.EditorFor(model => model.strName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.strName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<h5>Attention To</h5>
<div class="col-md-10">
#Html.EditorFor(model => model.strAttnTo, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.strAttnTo, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<h5>Street</h5>
<div class="col-md-10">
#Html.EditorFor(model => model.strStreet1, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.strStreet1, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<h5>Street 2</h5>
<div class="col-md-10">
#Html.EditorFor(model => model.strStreet2, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.strStreet2, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<h5>City</h5>
<div class="col-md-10">
#Html.EditorFor(model => model.strCity, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.strCity, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#{
IEnumerable<SelectListItem> dataItems = ViewBag.states;
}
<div class="form-group">
<h5>State</h5>
<div class="col-md-10">
#Html.DropDownListFor(model => model.State.IntStateId, dataItems, "-- Select --", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.State.IntStateId, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<h5>Zip</h5>
<div class="col-md-10">
#Html.EditorFor(model => model.strZip, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.strZip, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<h5>Phone Number</h5>
<div class="col-md-10">
#Html.EditorFor(model => model.strPhoneNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.strPhoneNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<h5>Set as Default</h5>
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.blnIsDefault)
#Html.ValidationMessageFor(model => model.blnIsDefault, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="button" class="btn btn-primary" data-ajax-method="get" data-toggle="ajax-modal"
data-url="#Url.Action("GetValidationOnAddress", new { model = Model })">
Verify Address
</button>
</div>
</div>
}
</div>
<script>
$(function () {
var PlaceHolderElement = $('#ValidateAddress');
$('button[data-toggle="ajax-modal"]').click(function (event) {
event.preventDefault();
var url = $(this).data('url');
// get the form containing the submit button
var form = $(this).closest('form')
// serialize all the fields in the form
var model = form.serialize();
// the the request to the url along with the form (model) data
$.get(url, model).done(function (data) {
PlaceHolderElement.html(data);
PlaceHolderElement.find('.modal').modal('show');
//$('#ValidateAddress').modal('show');
})
})
})
</script>
Here is the partial:
#model EcommerceWebsite.Models.Home.DeliveryAddressModel
<div class="modal fade" id="ValidateAddress">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="ValidateAddressLabel">Validate Address</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
#using (Html.BeginForm("AddShippingAddressToUser", "Home"))
{
#Html.HiddenFor(x => x.strName)
#Html.HiddenFor(x => x.strAttnTo)
#Html.HiddenFor(x => x.strStreet1)
#Html.HiddenFor(x => x.strStreet2)
#Html.HiddenFor(x => x.strCity)
#Html.HiddenFor(x => x.State.StrStateCode)
#Html.HiddenFor(x => x.State.StrStateName)
#Html.HiddenFor(x => x.State.IntStateId)
#Html.HiddenFor(x => x.strZip)
#Html.HiddenFor(x => x.strPhoneNumber)
#Html.HiddenFor(x => x.blnIsDefault)
<div class="modal-body">
<form action="Create">
<div class="form-group">
#if (Model.ErrorMessage == null)
{
<h5>#Model.strName</h5>
#if (Model.strAttnTo != null)
{<h5>#Model.strAttnTo</h5>}
<h5>#Model.strStreet1</h5>
#if (Model.strStreet2 != null)
{<h5>#Model.strStreet2</h5>}
<h5>#Model.strCity</h5>
<h5>#Model.State.StrStateCode</h5>
<h5>#Model.strZip</h5>
<h5>#Model.strPhoneNumber</h5>
<div class="modal-footer">
<button type="submit" value="Save" class="btn btn-primary">Save</button>
<button type="button" value="Edit" class="btn btn-secondary" data-dismiss="modal">Edit</button>
</div>
}
else
{
<h4>#Model.ErrorMessage</h4>
}
</div>
</form>
</div>
}
</div>
</div>
</div>
When all is said and done and the get validation button is pressed, it's supposed to send all the data to the controller and Verify the address with FedEx. But everything is null..
Now something to note, when I change the return of the httpget to return View(); everything works except it doesn't send the URL.
Update:
The AddShippingAddressToUser() hasn't even been called yet. The error lies somewhere in lines 101 - 102. Inside the button or the line 618 on the home controller.
Update: Here's the Model
public class DeliveryAddressModel
{
//[Required]
//[Display(Name = "First & Last Name")]
public string strName { get; set; }
//[Display(Name = "Attention To")]
public string strAttnTo { get; set; }
//[Required]
//[Display(Name = "Street 1")]
public string strStreet1 { get; set; }
//[Display(Name = "Street 2")]
public string strStreet2 { get; set; }
//[Required]
//[Display(Name = "City")]
public string strCity { get; set; }
//[Required]
//[Display(Name = "State")]
public Tstate State { get; set; }
//[Required]
//[Display(Name = "Zipcode")]
public string strZip { get; set; }
//[Required(ErrorMessage = "You must provide a phone number")]
//[Display(Name = "Phone Number")]
//[DataType(DataType.PhoneNumber)]
//[RegularExpression(#"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Not a valid phone number")]
public string strPhoneNumber { get; set; }
public bool blnIsDefault { get; set; }
public string ErrorMessage { get; set; }
public string strReturnAddress { get; set; }
}
First thing, since your form's function isnt a retrieval operation and a creational operation, use the http verb POST and not GET. Replace the HttpVerb filter above your action from HttpGet to HttpPost.
Second add this:
#using (Html.BeginForm("AddShippingAddressToUser", "Home", FormMethod.Post))
Alternatively,
#using (Html.BeginForm("AddShippingAddressToUser", "Home", FormMethod.Get))
Before your model in the action add: [FromQuery]

Insert data into database from another models view

I have two model classes for my project,
public class BookModel
{
public Int64 ISBN { get; set; }
public DateTime AddedDate { get; set; }
public bool isActive { get; set; }
public int Quantity { get; set; }
public int? FormatID { get; set; }
public virtual FormatModel Format { get; set; }
}
and
public class FormatModel
{
public FormatModel()
{
Books = new HashSet<BookModel>();
}
public int ID { get; set; }
public string Value { get; set; }
public virtual ICollection<BookModel> Books { get; }
}
I want to create a modal in my Create.cshtml file to add a new format if the specified format doesn't exist.
How can I create a Submit button for my modal to add the format in FormatModel?
This is my view:
#model RookBookMVC.Models.BookModel
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.ReturnUrl = "/Book/Create";
}
<h2>Create</h2>
#using (Html.BeginForm("Create", "Book", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>BookModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.FormatID, "FormatID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="input-group col-md-10">
#Html.DropDownList("FormatID", null, "Select Book Format", htmlAttributes: new { #class = "form-control" })
<div class="input-group-append">
<button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#exampleModalCenter">
Add New
</button>
</div>
</div>
#Html.ValidationMessageFor(model => model.FormatID, "", new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.LabelFor(model => model.ISBN, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ISBN, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ISBN, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Quantity, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Quantity, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Quantity, "", new { #class = "text-danger" })
</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>
}
#using (Html.BeginForm("Create", "Format", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">Add New Format</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
#Html.LabelFor(model => model.Format.Value, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Format.Value, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Format.Value, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<input type="submit" value="Create Format" class="btn btn-default" />
</div>
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
after I click on the 'Create Format' button. it returns false for ModelState.IsValid and doesn't add any data to my database
What should I do for making 'Create Format' Button make a new Entity for Format and save it in my database?
for Additional I need to create two models via a single page
You might have to create a View Model and pass the view model property as parameter to the Action - Format/ Create post.
ViewModel property:
public string FormatValue { get; set; }
Modal view:
#Html.EditorFor(model => model.FormatValue, new { htmlAttributes = new { #class = "form-control" } })
Controller code with parameter as the same name as the view model property being passed from the modal form:
[HttpPost]
public ActionResult Create(string formatValue)
{
using (var dataContext = new YourDbContextModel())
{
FormatModel fmtModel = new FormatModel();
fmtModel.Value = formatValue;
// rest of your code to save data
}
}
public class MYViewModel{ public string FormatValue { get; set; } }
Create.cshtml
#model MYViewModel
<div>
#Html.EditorFor(model => model.FormatValue, new { htmlAttributes = new { #class = "form-control" } })
</div>
Do You Mean something Like that?
OR
public class MYViewModel{
public string FormatValue { get; set; }
Public BookModel Book {get; set;}
}

Creating a subform to upload update another entity

this is driving me mad because it seems like such a basic thing, and yet I cannot for the life of me google it out...
I have Two Models in the Portfolio Part of my MVC website
public class PortfolioEntry
{
public int ID { get; set; }
[Display(Name="Project Name")]
public string Name { get; set; }
[Display(Name="Created for")]
public string Client { get; set; }
public string Description { get; set; }
[Display(Name ="Started at")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime Start { get; set; }
[Display(Name ="Ended by")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime End { get; set; }
[Display(Name ="Skills used")]
public string Category { get; set; }
[Display(Name ="GitHub Link")]
public string GitHubLink { get; set; }
[Display(Name ="Solution Screenshots")]
public virtual ICollection<ScreenShot> ScreenShots { get; set; }
}
And the second one:
public enum ScreenShotType
{
[Display(Name = "Use case Diagram")]
UseCase,
[Display(Name = "Behaviour Diagram")]
Behavior,
[Display(Name ="Class Diagram")]
ClassStructure,
[Display(Name ="Main View")]
MainPage,
[Display(Name = "Additional View")]
SomthingCool
}
public class ScreenShot
{
public int ID { get; set; }
public string Description { get; set; }
[Display(Name="Screenshot Type")]
public ScreenShotType Type { get; set; }
public string ImageURL { get; set; }
public int Sorting { get; set; }
public int PortfolioEntryID { get; set; }
}
}
Now what I want to do is create a subform that allows me to on the fly Upload a ScreenShot and create a new record in the database for it (you click browse..., select the photo, fill in the info for it and click "Upload").
Then return the "Main" form so I can either upload another one or just save the whole thing altogether.
How should I go about it? I Tried creating a new action in the controller:
public async Task<ActionResult> UploadPhoto([Bind(Include = "ID,Name,Client,Description,Start,End,GitHubLink")] PortfolioEntry portfolioEntry, HttpPostedFileBase uploadedFile, string description, int sorting)
{
if (uploadedFile!=null && uploadedFile.ContentLength>0 && uploadedFile.ContentType.Contains("image"))
{
string extension = Path.GetExtension(uploadedFile.FileName.ToString().ToLower());
string fileName = "PorfolioImage" + String.Format("{0:D5}", db.Photos.Count()) + extension;
var path = Path.Combine(Server.MapPath("~/Pictures/ScreenShots"), fileName);
uploadedFile.SaveAs(path);
var screenshotToAdd = new ScreenShot
{
Description = description,
Sorting = sorting,
PortfolioEntryID = portfolioEntry.ID,
ImageURL = fileName
};
await db.SaveChangesAsync();
}
return(View(portfolioEntry));
}
But:
1. It does not see the uploaded file
2. Even if it did see the file it does not seem to register the Entity from the Bind
I've seen one solution by: mkozicki but before I re-write the methods I'd like to know if it is the path I should take.
Adam
EDIT: As per the follow up adding the View:
#model KoscielniakInfo.Models.PortfolioEntry
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>PortfolioEntry</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Client, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Client, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Client, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Description, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Description, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Description, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Start, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Start, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Start, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.End, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.End, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.End, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.GitHubLink, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.GitHubLink, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.GitHubLink, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-1 col-md-10">
<table>
<tr>
#{
int cnt = 0;
foreach (var category in ViewBag.Categories)
{
if (cnt++ % 3 == 0)
{
#Html.Raw("</tr><tr>")
}
#Html.Raw("<td>")
<input type="checkbox"
name="selectedCategories"
value="#category.Name"
#(Html.Raw(category.Selected ? "checked=\"checked\"" : "")) />
#category.Name
#Html.Raw("</td>")
}
#Html.Raw("</tr>")
}
</table>
</div>
</div>
<div class="form-group">
<div id="newCats" class="col-md-10 col-md-offset-1">
<div id="newCat">
<h5>
New Category
</h5>
<input type="text" name="newCategories" /><br />
</div>
</div>
<div class="col-md-10 col-md-offset-1">
<input id="clone" type="button" value="More Categories" />
</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>
#*=================================This is the form Group for adding the photo ============================================*#
<div class="form-group">
<div class="row">
<div class="col-md-offset-2 col-md-3">
Description:
</div>
<div class="col-md-7">
<input type="text" name="description" id="description" />
</div>
</div>
<div class="row">
<div class="col-md-offset-2 col-md-3">
screenType:
</div>
<div class="col-md-7">
<input type="text" name="screenType" />
</div>
</div>
<div class="row">
<div class="col-md-offset-2 col-md-3">
Sorting:
</div>
<div class="col-md-7">
<input type="number" name="sorting" id="sorting" />
</div>
</div>
<div class="row">
<div class="col-md-offset-2 col-md-3">
Image:
</div>
<div class="col-md-7">
<input type="file" name="uploadedFile" />
</div>
<input type="button" value="Create" onclick="location.href='#Url.Action("UploadPhoto", "PorfolioEntries")'" />
</div>
</div>
//=============================================Ends Here =========================================================================
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$('#clone').click(function () {
$('#newCat').last().clone().appendTo('#newCats')
})
</script>
}

How to Bind ViewModel's object with the controller [duplicate]

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.

Send Data From View to Model With ViewModel

I have this ViewModel:
public class Rapport
{
[Key]
public int RapportId { get; set; }
public RapportAnomalie rapport { get; set; }
public IEnumerable<RefAnomalie> refAnomalies { get; set; }
}
which has two models in it, RapportAnomalie :
public class RapportAnomalie
{
[Key]
public int codeRapport { get; set; }
public DateTime date { get; set; }
public String heure { get; set; }
public String etat { get; set; }
[ForeignKey("codeAgence")]
public virtual Agence agence { get; set; }
public int codeAgence { get; set; }
public IEnumerable<LigneRapportAnomalie> lignesRapport { get; set; }
}
and RefAnomalie.
However when I want to send data from view to controller from a form, I keep getting an exception.
The view :
#model InspectionBanque.Models.Rapport
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>RapportAnomalie</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.rapport.date, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.rapport.date, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.rapport.heure, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.rapport.heure, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.rapport.etat, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.rapport.etat, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.rapport.codeAgence, "codeAgence", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("codeAgence", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.rapport.codeAgence, "", new { #class = "text-danger" })
</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>
}
#for (int i = 0; i < Model.refAnomalies.Count(); i++)
{
<div class="col-md-10">
#Html.DisplayFor(model => model.refAnomalies.ElementAt(i).libele)
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
and then the controller :
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create( Rapport rapportAnomalie)
{
if (ModelState.IsValid)
{
RapportAnomalie rp = new RapportAnomalie();
db.rapportAnomalies.Add(rapportAnomalie.rapport);
db.SaveChanges();
return RedirectToAction("Index");
}
var refanomal = from r in db.refAnnomalies
select r;
Rapport rapport = new Rapport { rapport = rapportAnomalie.rapport, refAnomalies = refanomal.ToArray() };
ViewBag.codeAgence = new SelectList(db.Agences, "codeAgence", "intituleAgence", rapportAnomalie.rapport.codeAgence);
return View(rapport);
}
Any ideas what's wrong with it?
I think you are getting the problem because the lignesRapport field is not initialized in your model RapportAnomalie
Create a constructor and initialize lignesRapport . I believe the problem will go away.
public RapportAnomalie()
{
lignesRapport = new List <LigneRapportAnomalie>();
}
Good luck

Categories