MVC 5 Creation of foreign key entities during primary entity creation - c#

I am utterly new to MVC and asp.net with Entity Framework so I am sure that most of my trouble stems from not knowing the proper terminology for what I am trying to do.
I have an "Address" database table/ entity that is a street address. Rather than having the street address fields in every entity that has an associated address, I simply have a foreign key column that points to the correct address in the address table.
For my Location creation view model, I have the following
public class LocationCreationViewModel
{
public address Address { get; set; }
[Key]
public location Location { get; set; }
}
It is probably worth pointing out that that View model is "hand made" while the address and location member objects are managed by the entity framework
My Create View has all of the location data, and then includes a partial address view which is rendered with
Html.Partial("_AddressCreate", Model.Location)
What currently happens is the LocationCreationViewModel returned in the Create(model) function is LocationCreationViewModel is null, or each of the fields is null. In any event, none of the data from the view is populated in the view model.
What I want to happen is that I get back the 2 addresses, add them to the address table in the database, then add my order to the order database with FK address fields pointing to the 2 newly created addresses.
I am using MVC5 and EF6 in visual studio 2017
Create.cshtml
#model MyWeb.Models.LocationCreationViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>location</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Location.name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Location.name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Location.name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Location.address, "address", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("address", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Location.address, "", new { #class = "text-danger" })
</div>
</div>
#Html.Partial("_AddressPartial", Model.Address)
<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>
_AddressPartial.cshtml
#model MyWeb.Data.address
<div class="form-horizontal">
<h4>address</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.country, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.country, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.country, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.locality, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.locality, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.locality, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.postalCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.postalCode, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.postalCode, "", new { #class = "text-danger" })
</div>
</div>
</div>
LocationController::Create
[MyWebAuthorize(MyWebRole = MyWebRole.Admin)]
public ActionResult Create()
{
ViewBag.address = new SelectList(db.addresses, "id", "country");
ViewBag.id = new SelectList(db.inventories, "locationID", "locationID");
LocationCreationViewModel model = new LocationCreationViewModel();
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create( LocationCreationViewModel location)
{
if (ModelState.IsValid)
{
db.addresses.Add(location.Address); //null reference exception here
db.locations.Add(location.Location);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.address = new SelectList(db.addresses, "id", "country", location.Location.address);
ViewBag.id = new SelectList(db.inventories, "locationID", "locationID", location.Location.id);
return View(location);
}

The autobinder failed to bind form data because of the field name Location in the View Model. I assume that this is due to Location being part of the page route. IE for the LocationController, the route would be /Location/Create
In any event, renaming LocationCreationViewModel::Location to LocationCreationViewModel::Locus fixed everything.

Related

How to pass dropDown list Selected data to another table and update that table in asp.Net MVC

The control class saves the input data into Invoice table.
This is my control class
public ActionResult UpdateInvoice()
{ var getProduct = db.InventoryTbs.ToList();
SelectList list = new SelectList(getProduct, "PId", "PName", "PPrice");
ViewBag.Product = list;
return View();
}
[HttpPost]
public ActionResult UpdateInvoice(InvoiceTb idetail)
{
if (Session["User"] == null) // doesn't work
{
return RedirectToAction("Login");
}
else
{
try
{
db.InvoiceTbs.Add(idetail);
db.SaveChanges();
return RedirectToAction("ShowInvoice");
}
catch
{
return View();
}
}
}
This is my UpdateInvoice.cshtml. Here if I input the Lquantity and Bill value gets saved into the Invoice table.
I have created dropdown list that shows item present in another table(inventory). But it doesnot add to Invoice table.
After entering the quantity I want it to calculate the bill taking selected product price from inventory table
I have tried Json and some other ways but finding no luck.
#model TallyBook_Store_Management_System.Models.InvoiceTb
#{
ViewBag.Title = "UpdateInvoice";
var product = ViewBag.Product;
}
<h2>UpdateInvoice</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>InvoiceTb</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.ListName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList( "Product", "Select")
#Html.ValidationMessageFor(model => model.ListName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.LQuantity, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.LQuantity, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.LQuantity, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Bill, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Bill, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Bill, "", 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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
I have solved the issue by passing drop down list selected data from view to controller. Then I have updated the specific database table in Controller.
If there is another efficient or good ways Please do share, I would like to learn more better approaches.

getting null reference in create view

I have created a method in the Employee controller for creating a new Employee:
[HttpGet]
[ActionName ("Create")]
public ActionResult Create()
{
return View();
}
I have Added a view for Create method with Employee(strongly-typed)model and used the create template.
When I run the program and click on create new I get a null reference error in create view.
#model BuissnessLayer.Employee
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Employee</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.Employee_Id, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee_Id, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee_Id, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Employee_Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee_Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee_Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Employee_Age, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee_Age, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee_Age, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Employee_City, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee_City, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee_City, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Employee_Salary, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Employee_Salary, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Employee_Salary, "", 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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
<script src="~/Scripts/jquery-3.4.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
I get the error at line
#Html.EditorFor(model => model.Employee_Id, new { htmlAttributes = new { #class = "form-control" } })
I don't know how to solve the problem because the code is created automatically and i haven't edited anything yet.
You should pass model to your View..
[HttpGet]
[ActionName ("Create")]
public ActionResult Create()
{
var model = new Employee(){}
return View(model);
}
#model BuissnessLayer.Employee

DropDownListFor post value NULL to database

I have a Course Table and a Hole Table in SQL. There is a foreign Key in the hole Table that is set to the CourseId.
This is so that when I create a hole I can assign it to the relevant course.
In my View I have a dropdownlistfor that has a list of courses to select from when creating the hole. However when I try and post back the values the courseID does not post back.
HoleViewModel
// GET: HoleViewModels/Create
public ActionResult Create()
{
var dbcourse = db.Course.ToList();
//Make selectlist, which is IEnumerable<SelectListItem>
var courseNameDropdownList = new SelectList(db.Course.Select(item => new SelectListItem()
{
Text = item.CourseName.ToString(),
Value = item.CourseId.ToString()
}).ToList(), "Value", "Text");
// Assign the Selectlist to the View Model
var viewCourse = new HoleViewModel()
{
Course = dbcourse.FirstOrDefault(),
// The Dropdownlist values
CourseNamesDropdownList = courseNameDropdownList,
};
return View(viewCourse);
}
// POST: HoleViewModels/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "HoleId,HoleNumber,Par,Length,StrokeIndex,CourseId")] HoleViewModel holeViewModel)
{
if (ModelState.IsValid)
{
db.HoleViewModels.Add(holeViewModel);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(holeViewModel);
}
The Create.cshtml
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>HoleViewModel</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.HoleNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.HoleNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.HoleNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Par, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Par, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Par, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Length, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Length, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Length, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.StrokeIndex, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.StrokeIndex, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.StrokeIndex, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Course.CourseId, "CourseId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.Course.CourseId, Model.CourseNamesDropdownList, "Please select from List", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.CourseId, "", new { #class = "text-danger" })
</div>
</div>
So when the holeview posts back holeNumber, Par, Length, StrokeIndex, CourseID. it passes all data into the hole table other than the courseId which it posts a null.
What am I missing from the POST to get the CourseId to be entered in the Database.

How to get back uploaded image in edit mode in my form using ASP.NET MVC 5?

I have created a form and I am inserting some data and image in my database using the form submit... But when I am opening in edit mode, all inserted data is available in the input fields except the image? How do I fix this?
View:
#model User_Management_System_V2._0.Models.Product
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm("Edit","Products",FormMethod.Post , new { enctype = "multipart/form-data"}))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Product</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#*<div class="form-group">
#Html.LabelFor(model => model.ProductID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ProductID, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductID, "", new { #class = "text-danger" })
</div>
</div>*#
#Html.HiddenFor(model => model.ProductName)
<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.PriceExpected, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PriceExpected, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PriceExpected, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.OldTime, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.OldTime, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OldTime, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Status, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Status, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Status, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Photo, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="file" name="file"/>
#Html.ValidationMessageFor(model => model.Photo, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Controller:
public ActionResult Edit(string id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Product product = db.Products.Find(id);
if (product == null)
{
return HttpNotFound();
}
return View(product);
}
Create Action
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create([Bind(Include = "ProductName,Description,PriceExpected,OldTime,Status,Photo")]Product product,HttpPostedFileBase file)
{
if (file != null)
{
product.Photo = new byte[file.ContentLength];
file.InputStream.Read(product.Photo, 0, file.ContentLength);
}
else
{
ModelState.AddModelError("", "Please Select image");
}
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("Index");
}
My main problem is that all the fields are opening in edit mode which means they are opening in edit mode with the preinserted data values in their fields but the image is not having the preinserted value.
try the following solution in jquery and pure Javascript you will only need to retrieve byte array of the image you uploaded and it's extension then just give your image control the generated src I hope it helps
var PhotoArr = []; //array of bytes from the server
var PhotoExt = "jpg";//example
if (PhotoArr) {
var byteArray = new Uint8Array(oldResume.PhotoArr);
var blob = new Blob([byteArray], { type: 'application/' + PhotoExt });
var image = $('#yourImageId');
var urlCreator = window.URL || window.webkitURL;
var imageUrl = urlCreator.createObjectURL(blob);
image.attr('src', imageUrl);
}

Consuming a web service and auto populate textbox by the given xml data after clicking a button in asp.net mvc

i have textbox where a voter id will be given as an input,besides that there is "show information" button. After clicking that textbox of "name","address","age" will be populated. the information is to be retrieved from http://nerdcastlebd.com/web_service/voterdb/index.php/voters/voter/9509623450915. Last slash has the voter id. I have been through many resources but cant get a hold of them. i am new in mvc. Plz help
<div class="form-group">
#Html.LabelFor(model => model.patient.voter_id,"Voter Id", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.patient.voter_id, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.patient.voter_id, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Voter Information" id="btnVoter" class="btn btn-default" />
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.patient.name,"Name", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.patient.name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.patient.name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.patient.age,"Age", htmlAttributes: new {#class = "control-label col-md-2"})
<div class="col-md-10">
#Html.EditorFor(model => model.patient.age, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.patient.age, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.patient.address,"Address", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.patient.address, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.patient.address, "", new { #class = "text-danger" })
</div>
</div>
You can do this on client side (View) with jQuery and the flow will look similar to the one i described below.
1) Attach .click() event to button to call the service and populate the fields when is pressed.
2) Get the id and concatenate to base url. With this make a GET call to take data from service.
3) After you get data from service you can populate your fields.
$('#btnVoter').click(function(){
var id = $('#voterId').val();
$.get('http://nerdcastlebd.com/web_service/voterdb/index.php/voters/voter/' + id, function(data, status) {
$('#voterName').val(data.name);
// populate other (address, age) data on page
});
});
Notes: The ids i used may not match your inputs id on page, please update them accordingly.

Categories