I'm new to MVC and have spent several hours trying to find a solution to this issue. I'm trying to set up an invoicing system for some rental properties. The property manger provides an excel file that contains the current water readings. I have to subtract the water readings from last months to find out the monthly usage. The view I've made does this and shows all the units simultaneously. What I'm having problems with is passing the uploaded file along with the model data (last months readings) to the controller. The file shows up but none of the other data.
In the view I have two submit buttons. One to upload the file to be integrated into the model data and the other to create the new records based on the previous and current(uploaded) data. Below are the relevant model, view and controllers.
Ultimately the billing manger would see last month's data, upload the new data, review and verify there are no errors and then submit the data for the new invoices.
If there is better way to accomplish that then what I'm trying here please let me know. This just seemed like it would be easier that recreating model data with all the linq queries. Thanks in advance for your help!
Model:
public partial class UtilityData
{
public DateTime bEntryDate { get; set; }
public string bPrevDate { get; set; }
public int bID { get; set; }
//public int residenceCount { get; set; }
public IEnumerable<UtilEntry> utilData { get; set; }
public HttpPostedFileBase UploadFile { get; set; }
}
public partial class UtilEntry
{
public int rID { get; set; }
public long? WaterReading { get; set; }
public int ResNumber { get; set; }
public long? prevWaterReading { get; set; }
public decimal wDifference { get; set; }
public int GrnUpper { get; set; }
public int GrnLower { get; set; }
public int YelUpper { get; set; }
public int YelLower { get; set; }
}
View:
#model PropertiesAdminSite.Models.UtilityData
#{
ViewBag.Title = "CreateNewCycle";
}
<h2>New Residence Utilities</h2>
#using (Html.BeginForm("Upload", "ImportWater", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="control-group">
#Html.TextBoxFor(m => m.UploadFile, new { type = "file"})
#*<input type="file" class="btn btn-info" name="postedFile"/>*#
</div>
<div class="control-group">
<input type="submit" class="btn btn-info" value="Upload" />
</div>
<div class="col-lg-12 visible-lg">
<br>
<span style="color:green">#ViewBag.Message</span>
</div>
}
#using (Html.BeginForm("IndexMulti", "Utilities", FormMethod.Post))
{
#Html.AntiForgeryToken()
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
#Html.LabelFor(model => model.bEntryDate, htmlAttributes: new { #class = "control-label col-md-1" })
#Html.DisplayFor(model => model.bEntryDate)
</div>
<!-- /.panel-heading -->
<div class="panel-body">
<div class="dataTable_wrapper">
<!--div id="dataTables-example_wrapper" class="dataTables_wrapper form-inline dt-bootstrap no-footer">-->
<div class="row">
<div class="col-sm-12">
<table class="table table-striped table-bordered table-hover dataTable no-footer" id="dataTables-Bills" role="grid" aria-describedby="dataTables-example_info">
<!-- /table headers-->
<thead>
<tr role="row">
<th>#Html.DisplayNameFor(model => model.utilData.First().ResNumber)</th>
<th>#Html.DisplayNameFor(model => model.utilData.First().WaterReading)</th>
<th>
#Html.DisplayNameFor(model => model.utilData.First().prevWaterReading)
#* TODO: fix date format *#
#Html.DisplayFor(model => model.bPrevDate)
</th>
<th>#Html.DisplayNameFor(model => model.utilData.First().wDifference)</th>
<th>Actions</th>
</tr>
</thead>
<!-- /table body-->
<tbody>
#foreach (var item in Model.utilData)
{
<tr role="row">
<td>
#Html.DisplayFor(modelItem => item.ResNumber, null, "residence_" + item.rID)
#Html.HiddenFor(model => item.GrnLower, new { id = "grnLower_" + item.rID })
#Html.HiddenFor(model => item.GrnUpper, new { id = "grnUpper_" + item.rID })
#Html.HiddenFor(model => item.YelLower, new { id = "yelLower_" + item.rID })
#Html.HiddenFor(model => item.YelUpper, new { id = "yelUpper_" + item.rID })
</td>
<td>
#Html.EditorFor(model => item.WaterReading, null, "waterReading_" + item.rID)
</td>
<td>
<span id="#string.Format("prevWater_{0}",item.rID)">
#Html.DisplayFor(model => item.prevWaterReading, null, "prevWater_" + item.rID)
</span>
#Html.HiddenFor(model => item.prevWaterReading, new { id = "hprevWater_" + item.rID })
</td>
<td>
<span id="#string.Format("hdifference_{0}",item.rID)">
#Html.DisplayFor(model => item.wDifference)
</span>
#Html.HiddenFor(model => item.prevWaterReading, new { id = "hdifference_" + item.rID })
</td>
<td>
#Html.ActionLink("View History", "ExportDataIndex", "ExportData", new { rID = item.rID, bId = Model.bID }, null) |
<a href="#Url.Action("ExportToExcel", "ExportData", new { rID = item.rID, bId = Model.bID })" class="btn btn-success">
<i class="fa fa-file-excel-o" aria-hidden="true" title="Export to Excel"></i>
</a> |
<a href="#Url.Action("ChartData", "Utilities", new { rID = item.rID, bId = Model.bID })" class="btn btn-info">
<i class="fa fa-bar-chart" aria-hidden="true" title="Water Usage History"></i>
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</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>
}
Controller:
// GET: ImportWater
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Upload([Bind(Include = "bEntryDate,bPrevDate,bID,utilData,UploadFile")]UtilityData uData) //<----The file gets uploaded but none of the Model data from the view.
{
HttpPostedFileBase postedFile = uData.UploadFile;
if (postedFile != null && postedFile.ContentLength > 0)
{
string fileName = postedFile.FileName;
string fileContentType = postedFile.ContentType;
byte[] fileBytes = new byte[postedFile.ContentLength];
var data = postedFile.InputStream.Read(fileBytes, 0, Convert.ToInt32(postedFile.ContentLength));
using (var package = new ExcelPackage(postedFile.InputStream))
{
//Todo: read file and insert data
}
ViewBag.Message = "File uploaded successfully.";
}
return View(uData);
}
I now understand what the issue was; I didn't fully understand how the POST worked. I thought the form would always send the full model object back and that is not the case. I created hidden items to capturethe model data I wanted to post back.
#using (Html.BeginForm("Upload", "ImportWater", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="control-group">
#Html.TextBoxFor(m => m.UploadFile, new { type = "file"})
#*<input type="file" class="btn btn-info" name="postedFile"/>*#
</div>
<div class="control-group">
<input type="submit" class="btn btn-info" value="Upload" />
</div>
<div class="col-lg-12 visible-lg">
<br>
<span style="color:green">#ViewBag.Message</span>
#Html.HiddenFor(model => model.bID)
#Html.HiddenFor(model => model.bEntryDate)
#Html.HiddenFor(model => model.bPrevDate)
#for (int i = 0; i < Model.utilData.Count(); i++)
{
#Html.HiddenFor(model => model.utilData[i].ResNumber)
#Html.HiddenFor(model => model.utilData[i].GrnLower)
#Html.HiddenFor(model => model.utilData[i].GrnUpper)
#Html.HiddenFor(model => model.utilData[i].prevWaterReading)
#Html.HiddenFor(model => model.utilData[i].rID)
#Html.HiddenFor(model => model.utilData[i].WaterReading)
#Html.HiddenFor(model => model.utilData[i].wDifference)
#Html.HiddenFor(model => model.utilData[i].YelLower)
#Html.HiddenFor(model => model.utilData[i].YelUpper)
}
</div>
}
Related
I would like to use generate IDs depending on the models variable name.
I have two models
public class ConceptViewModel
{
[AllowHtml]
public string Content { get; set; }
[AllowHtml]
public string EnglishContent { get; set; }
public string Instructions { get; set; }
}
and
public class InputDataCollectionViewModel
{
public int Id { get; set; }
public ConceptModel Definition { get; set; }
public ConceptModel Publication { get; set; }
public bool Exist { get; set; }
}
I'm using EditorTemplates for ConceptViewModel:
#model Models.ConceptViewModel
<tr>
<td>#Html.LabelFor(m => m, htmlAttributes: new { #class = "control-label" })</td>
<td hidden>
#Html.TextBoxFor(m => Content, (#Model.Exist ? null : (object)new { #disabled = "disabled" }))
#Html.TextBoxFor(m => m.EnglishContent)
</td>
<td hidden>#Html.TextBoxFor(m => m.Instructions)</td>
<td><button type="button" class="btn btn-default" onclick="openEditor('UNIQUE_NAME_DEPENDING_ON_MODEL_NAME');">Edit</button></td>
</tr>
and the view:
#model Models.InputDataCollectionViewModel
<div class="container">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
{
<div class="form-group">
#Html.HiddenFor(model => model.Id)
<table class="table table-hover table-condensed">
<tbody>
#Html.EditorFor(model => model.Definition)
#Html.EditorFor(model => model.Publication)
</tbody>
<tfoot></tfoot>
</table>
<div class="row">
<div class="col-md-12">
<button class="btn btn-default" type="submit">Save</button>
</div>
</div>
</div>
}
}
which generates html containing:
<label class="control-label" for="Definition">
<input id="Definition_Content" name="Definition.Content" type="text" value="" />
<input id="Definition_EnglishContent" name="Definition.EnglishContent" type="text" value="" />
<input id="Definition_Instructions" name="Definition.Instructions" type="text" value="..." />
and the same for the other ConceptViewModels. So from this I can easily reference it because of the unique IDs (Definition_, Publication_ and so forth for other inputs I have elsewhere).
Now my question is, how would I get the strings containg "Definition", "Publication" so I could use it with the generated buttons. What I want is:
openEditor('Definition');
openEditor('Publication');
in the onclick.
I've managed to find the solution. The Html helper #Html.IdFor(m => m)
I have recently learning ASP.NET MVC5.
I am trying to see both the form and a table(return as partialview) in one view but i'm getting this error.
System.NullReferenceException: Object reference does not set to an instance of an object.
Here is my Model:
public class Prescription
{
[Key]
public int PrescriptionID { get; set; }
[ForeignKey("Assessment")]
public int? AssessmentID { get; set; }
public Assessment Assessment { get; set; }
[ForeignKey("Medicine")]
[Display(Name ="Prescription")]
public int? MedcineID { get; set; }
public Medicine Medicine { get; set; }
}
My main view where I want to put my partial view:
#using ClinicManagemet
#model ClinicManagemet.Models.Prescription
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Prescription</h4>
<hr />
<div class="form-group">
#Html.LabelFor(model => model.MedcineID, "MedcineID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("MedcineID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.MedcineID, "", 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>
}
#Html.Action("ViewPrescription","Assessments")
<div>
#Html.ActionLink("Back to Home", "Home")
</div>
My partial view:
#model IEnumerable<ClinicManagemet.Models.Prescription>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Assessment.Complaint)
</th>
<th>
#Html.DisplayNameFor(model => model.Medicine.MedicineName)
</th>
<th></th>
</tr>
#foreach (var item in Model) { //Here is the line where I get the error
<tr>
<td>
#Html.DisplayFor(modelItem => item.Assessment.Complaint)
</td>
<td>
#Html.DisplayFor(modelItem => item.Medicine.MedicineName)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.PrescriptionID }) |
#Html.ActionLink("Details", "Details", new { id=item.PrescriptionID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.PrescriptionID })
</td>
</tr>
}
</table>
My partial view's controller:
public ActionResult ViewPrescription()
{
return PartialView();
}
Edit: If I fix this, I'll try to add Ajax so whenever I insert something, it will just refresh the partial view.
Load your partial view like this,
#{
Html.RenderAction("ViewPrescription","YourControllerName")
}
And in your ViewPrescription method, return the data,
{
//Fetch the data here
return PartialView(model);
}
Hope it helps.
You're not passing a model into the partial view when returning the view.
public ActionResult ViewPrescription()
{
ClinicManagemet.Models.Prescription model = _service.GetPerscription();
return PartialView(model);
}
I am writing a web page with MVC and Entity Framework.
I have an order with line items attached and want to return a complex object to the controller for processing.
I have now included all the code.
My view:
#model BCMManci.ViewModels.OrderCreateGroup
#{
ViewBag.Title = "Create";
}
<h2>New Order</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<h4>#Html.DisplayFor(model => model.Order.Customer.FullName)</h4>
<table>
<tr>
<td><b>Order Date:</b> #Html.DisplayFor(model => model.Order.OrderDate)</td>
<td><b>Status:</b> #Html.DisplayFor(model => model.Order.OrderStatus.OrderStatusName)</td>
</tr>
<tr>
<td colspan="2">
<b>Notes</b>
#Html.EditorFor(model => model.Order.Notes, new { htmlAttributes = new { #class = "form-control" } })
</td>
</tr>
</table>
#Html.ValidationMessageFor(model => model.Order.Notes, "", new { #class = "text-danger" })
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<table class="table table-striped table-hover">
<thead>
<tr>
<td>Name</td>
<td>Price</td>
<td>Discount</td>
<td>Total</td>
<td>Quantity</td>
</tr>
</thead>
<tbody>
#foreach (var product in Model.ProductWithPrices)
{
<tr>
<td>
#Html.DisplayFor(modelItem => product.ProductName)
</td>
<td>
#Html.DisplayFor(modelItem => product.SellingPrice)
</td>
<td>
#Html.DisplayFor(modelItem => product.DiscountPrice)
</td>
<td>
#Html.DisplayFor(modelItem => product.TotalPrice)
</td>
<td>
#Html.EditorFor(modelItem => product.Quantity, new { htmlAttributes = new { #class = "form-control" } })
</td>
</tr>
}
</tbody>
</table>
<input type="submit" value="Create" class="btn btn-default" />
}
<div class="btn btn-danger">
#Html.ActionLink("Cancel", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Order,ProductWithPrices,Order.Note,product.Quantity")] OrderCreateGroup order)
{
try
{
if (ModelState.IsValid)
{
db.Orders.Add(order.Order);
foreach (var orderItem in order.ProductWithPrices.Select(item => new OrderItem
{
OrderId = order.Order.OrderId,
ProductId = item.ProductId,
Quantity = item.Quantity,
ItemPrice = item.SellingPrice,
ItemDiscount = item.DiscountPrice,
ItemTotal = item.TotalPrice
}))
{
db.OrderItems.Add(orderItem);
}
db.SaveChanges();
return RedirectToAction("ConfirmOrder", new {id = order.Order.OrderId});
}
}
catch (DataException /* dex */)
{
//TODO: Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
ViewBag.Products = db.Products.Where(model => model.IsActive == true);
PopulateDropdownLists();
return View(order);
}
Data Source:
public class OrderCreateGroup
{
public OrderCreateGroup()
{
ProductWithPrices = new List<ProductWithPrice>();
}
public Order Order { get; set; }
public ICollection<ProductWithPrice> ProductWithPrices { get; set; }
}
public class ProductWithPrice : Product
{
public decimal SellingPrice { get; set; }
public decimal DiscountPrice { get; set; }
public int Quantity { get; set; }
public decimal TotalPrice { get; set; }
}
However, the values that are entered on the form are not being passed, through. So I can't access them in the controller. The 'productWithPrices' collection is null although there is Data in it on the web page.
I have tried making it asyc and also tried changing the ActionLink button like below but it didn't get to the controller.
#Html.ActionLink("Create", "Create", "Orders", new { orderCreateGoup = Model }, null)
This is the controller but it now doesn't make sense as the parameter passed in the datasource for the page.
public ActionResult Create(OrderCreateGroup orderCreateGoup)
Please, can you give me direction on the best way of doing this?
In your OrderCreateGroup class initialize the collection to an empty list.
public class OrderCreateGroup
{
public OrderCreateGroup()
{
ProductWithPrices = new List<ProductWithPrice>();
}
public Order Order { get; set; }
public ICollection<ProductWithPrice> ProductWithPrices { get; set; }
}
You'll need to add #Html.HiddenFor(m => m.SellingPrice) and similarly for other bound fields that are using DisplayFor if you want to post them back to the controller.
Note: For your benefit, try to have a look at the generated HTML code when your page is rendered in the browser and see what tags are generated inside the <form> tag with a name attribute.
make sure you bind the appropriate property from the complex object, like the following:
#model BCMManci.ViewModels.OrderCreateGroup
...
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
...
<div class="form-group">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.OrderCreateGroup.Order.Quantity, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.OrderCreateGroup.Order.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>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
Note:model.OrderCreateGroup.Order.Quantity would be one the your order's property.
hope this helps.
I have read several answers on this issue but despite this, it would appear I have developed code blindness.
I have the following view model:
public class IndividualProductVm
{
public virtual Products Products { get; set; }
public ProductSummary ProductSummary { get; set; }
public virtual IEnumerable<ProductSimpleResponse> ProductSimpleResponse { get; set; }
}
This is then passed into a view and then a partial view:
#model Websites.ViewModels.IndividualProductVm #{ ViewBag.Title = "Edit"; }
<h2>Edit</h2>
#using (Html.BeginForm(null, null, FormMethod.Post, new { name = "form", id = "mainForm" })) { #Html.AntiForgeryToken() #Html.ValidationSummary(true, "", new { #class = "text-danger" }) #Html.HiddenFor(model => model.Products.Id) #Html.HiddenFor(model
=> model.ProductSummary.SupplierId) Html.RenderPartial("_IndividualProduct", Model);
<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>
#Html.ActionLink("Back to List", "Index", new { id = Model.ProductSummary.SupplierId }, new { #class = "btn btn-default" })
</div>
#section Scripts { #Scripts.Render("~/bundles/jqueryval") }
#model Websites.ViewModels.IndividualProductVm
<div>
#Html.LabelFor(model => model.Products.ProductCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div>
#Html.DisplayFor(model => model.Products.ProductCode, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div style="clear:both;"></div>
<div>
#Html.LabelFor(model => model.Products.ProductDescription, htmlAttributes: new { #class = "control-label col-md-2" })
<div>
#Html.DisplayFor(model => model.Products.ProductDescription, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<table class="table">
<tr>
<th>
Present
</th>
</tr>
#foreach (var item in Model.ProductSimpleResponse)
{
<tr>
#Html.HiddenFor(modelItem => item.Id)
#Html.HiddenFor(modelItem => item.SupplierId)
#Html.HiddenFor(modelItem => item.ProductCode)
<td>
#Html.EditorFor(modelItem => item.Present)
</td>
</tr>
}
</table>
However, when I enter the edit post, my viewmodel is null for the IEnumerable<ProductSimpleResponse> but fine for the other two classes.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(IndividualProductVm model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index", new { id = model.ProductSummary.SupplierId });
}
return View(model.Products);
}
If someone can explain what I'm doing wrong, I'd be most grateful.
Your property name is ProductSimpleResponse, alhtough the type is ProductSvhcSimpleResponse, so to iterate through it you should have.
#foreach (var item in Model.ProductSimpleResponse)
NOT
#foreach (var item in Model.ProductSvhcSimpleResponse)
use List because
IEnumerable is suitable just for iterate through collection and you can not modify (Add or Remove) data IEnumerable bring ALL data from server to client then filter them, assume that you have a lot of records so IEnumerable puts overhead on your memory.
public class IndividualProductVm
{
public virtual Products Products { get; set; }
public ProductSummary ProductSummary { get; set; }
public virtual List<ProductSvhcSimpleResponse> ProductSimpleResponse { get; set; }
}
More help click here
I have a listing view which shows the jobs extracted from the database. Each Job has a button next to it. When I move to the next page, i need to carry the specified job, display it and later save it to my database.
This is inside my Controller class.
I extracted the jobs in the index and after clicking the button i want to move to the "Apply" method
public ActionResult Index()
{
var jobs = (from Jobs in db.Jobs
orderby Jobs.Id descending
select Jobs);
List<CareersClasses.Jobs> job = jobs.ToList();
return View(job);
}
[HttpPost]
public ActionResult Apply(){
return View();
}
This is The Index View:
<table>
#using (Html.BeginForm("Apply", "Jobs", FormMethod.Post))
{
foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Desc)
</td>
<td>
<button id="Apply" name="Apply" value="#item.Title">Apply</button>
</td>
</tr>
}
}
</table>
This is the Apply View
#using (Html.BeginForm("Submit", "Jobs", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<fieldset>
<legend>Applicants</legend>
<div class="editor-label">
#Html.LabelFor(model => model.JobId)
</div>
<div class="editor-field">
#Html.DisplayFor(model=> model.JobId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FName)
#Html.ValidationMessageFor(model => model.FName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LName)
#Html.ValidationMessageFor(model => model.LName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Email)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Email)
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PhoneNb)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PhoneNb)
#Html.ValidationMessageFor(model => model.PhoneNb)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Country)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Country)
#Html.ValidationMessageFor(model => model.Country)
</div>
<div class="editor-label">
Curriculum Vitae
</div>
<div class="editor-field">
<input type="file" name="file"/>
</div>
<div class="editor-label">
#Html.EditorFor(model => model.JobId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
I also want to add a document to my database:
I used this method in the "submit" method is it correct?
Submit Method:
[HttpPost]
public ActionResult Submit(FormCollection formCollection, HttpPostedFileBase file)
{
CareersClasses.Applicants Applicants = new CareersClasses.Applicants();
if (ModelState.IsValid)
{
Applicants.FName = formCollection["FName"];
Applicants.LName = formCollection["LName"];
Applicants.Email = formCollection["Email"];
Applicants.Country = formCollection["Country"];
Applicants.PhoneNb = int.Parse(formCollection["PhoneNb"]);
if (file != null && file.ContentLength > 0)
{
byte[] data = GetDocument(file);
Applicants.CV = data;
}
db.Applicants.Add(Applicants);
db.SaveChanges();
return RedirectToAction("ListApps");
}
return View();
}
[HttpPost]
public byte[] GetDocument(HttpPostedFileBase file)
{
//Get file info
var fileName = Path.GetFileName(file.FileName);
var contentLength = file.ContentLength;
var contentType = file.ContentType;
//Get file data
byte[] data = new byte[] { };
using (var binaryReader = new BinaryReader(file.InputStream))
{
data = binaryReader.ReadBytes(file.ContentLength);
}
return data;
}
The Classes Model:
public class CareersClasses
{
public class Applicants
{
[Key]
public int Id { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public int PhoneNb { get; set; }
public string Email { get; set; }
public string Country { get; set; }
public byte[] CV { get; set; }
public int JobId { get; set; }
[ForeignKey("JobId")]
public virtual Jobs Jobs { get; set; }
}
public class Jobs
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Desc { get; set; }
}
}
Note: I am still new to MVC and I did a lot of research before asking these questions but i'm still lost, so your help will be much appreciated
The Index view should have links (not forms) to an Apply() method for the Job. The link passes the Id of the Jobs to the method, which initializes a new instance of CareersClasses and sets its JobId property. The method then returns a view to edit the CareersClasses and the submit button posts back the model to the POST method.
Index.cshtml
<table>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(modelItem => item.Title)</td>
<td>#Html.DisplayFor(modelItem => item.Desc)</td>
<td>#Html.ActionLink("Apply", "Apply", new { ID = item.Id})</td>
</tr>
}
</table>
Controller
public ActionResult Apply(int ID)
{
CareersClasses model = new CareersClasses();
model.JobID = ID;
return View(model);
}
[HttpPost]
public ActionResult Apply(CareersClasses model, HttpPostedFileBase file)
{
// save the model and redirect
}
Apply.cshtml
#model CareersClasses
....
#Html.BeginForm())
{
// controls for properties of CareersClasses
....
<input type="submit" value="Create" />
}