How to upload and save muliple images to database - asp.net-mvc-4

I have this action method:
[HttpPost]
public ActionResult UploadMorePhotos(UserProfile userProfile, IEnumerable<HttpPostedFileBase>files)
{
foreach (var file in files)
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
//ModelState.Clear();
}
if (ModelState.IsValid)
{
string username = User.Identity.Name;
// Get the userprofile
UserProfile user = db.userProfiles.FirstOrDefault(u => u.UserName.Equals(username));
// Update fields
user.Image = new byte[file.ContentLength];
file.InputStream.Read(user.Image, 0, file.ContentLength);
user.ImageMimeType = file.ContentType;
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
}
return Redirect(Url.Action("Edit", "Account") + "#tabs-3");
}
return View(userProfile);
}
This is my view:
<div id="tabs-3">
hallo
#using (Html.BeginForm("UploadMorePhotos", "Account", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
<div class="form-field">
<p>Select pictures:</p>
<div class="upload-container">
<div class="upload">
<input type="file" name="files" id="file1" />
<img src="#Url.Content("~/images/deleteButton.png")" alt="Remove picture." />
</div>
</div>
</div>
<div class="form-field">
<input type="submit" value="Create" />
</div>
}
</div>
I want to store more Images to Database. A user can select one or more images and the images have to be saved to the database after uploading.
but on this line:
user.Image = new byte[files.ContentLength];
contentLength is not recognised.
Thank you
And this is my model:
public partial class UserProfile
{
public int Id { get; set; }
public string UserName { get; set; }
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Display(Name = "Last Name")]
public string LastName { get; set; }
public string Email { get; set; }
[Display(Name = "Motto")]
public string Motto { get; set; }
[Display(Name = "Place of birth")]
public string PlaceOfBirth { get; set; }
[Display(Name = "How many bikes")]
public int HowManyBikes { get; set; }
[Display(Name = "Are they beside your bed")]
public string BesideYourBeth { get; set; }
[Display(Name = "Nicest ride")]
public string NicestRide { get; set; }
[Display(Name = "Worst ride")]
public string WorstRide { get; set; }
[Display(Name = "Amount of k's per year")]
public string AmountKmPerYear { get; set; }
[Display(Name = "Average speed")]
public string AverageSpeed { get; set; }
[Display(Name = "Able to chat while riding")]
public string AbleToChatWhileRiding { get; set; }
[Display(Name = "Phone number")]
public string PhoneNumber { get; set; }
public string Picture { get; set; }
[Column(TypeName = "image")]
[DisplayName("Image")]
[MaxLength]
public byte[] Image { get; set; }
[Display(Name = "Display profile Image")]
public bool DisplayItem { get; set; }
[DisplayName("ImageMimeType")]
public string ImageMimeType { get; set; }
public virtual ICollection<LolaBikePhoto> LolaBikePhotos { get; set; }
}
IF I select mulitiple images for example two I only see one photo in the map: \App_Data\Uploads.
Because A user can have 1 or more photos on his profile.
I add this:
if (user != null)
{
var lolaphoto = new LolaBikePhoto
{
UserProfileID = user.Id
};
// lolaphoto.UserProfileID = 47;
db.lolabikerPhotos.Add(lolaphoto);
}

Related

ASP.NET Core Assign database values to a dropdown list for Edit action

I have a controller with CRUD autogenerated and I am trying to fill values fetched from database to a dropdown.
My model class is like below
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace ERPCustomerSupplier.Models
{
public class Customer
{
[Display(Name = "ID")]
public int ID { get; set; }
[Display(Name = "User")]
public string REQ_USERNAME { get; set; }
[Display(Name = "Date")]
public string REQ_DATE { get; set; }
[Display(Name = "Status")]
public string STATUS { get; set; }
[Display(Name = "Customer Type")]
public string CUSTOMER_TYPE { get; set; }
[Display(Name = "Number")]
public string CUSTOMER_NUMBER { get; set; }
[Display(Name = "Name")]
public string ORGANIZATION_NAME { get; set; }
[Display(Name = "Country")]
public string COUNTRY { get; set; }
[Display(Name = "Address")]
public string ADDRESS_LINE { get; set; }
[Display(Name = "City")]
public string CITY { get; set; }
[Display(Name = "State")]
public string STATE { get; set; }
[Display(Name = "Operating Unit")]
public string OPERATING_UNIT { get; set; }
[Display(Name = "Currency")]
public string CURRENCY { get; set; }
[Display(Name = "Credit Limit")]
public string CREDIT_LIMIT { get; set; }
[Display(Name = "Credit Terms")]
public string CREDIT_TERMS { get; set; }
[Display(Name = "Bill To")]
public string BILL_TO { get; set; }
[Display(Name = "Ship To")]
public string SHIP_TO { get; set; }
[Display(Name = "Contact Person")]
public string CT_PERSON { get; set; }
[Display(Name = "Job Title")]
public string CT_JOB_TITLE { get; set; }
[Display(Name = "Department")]
public string CT_DEPARTMENT { get; set; }
[Display(Name = "Mobile")]
public string CT_MOBILE { get; set; }
[Display(Name = "Email")]
public string CT_EMAIL { get; set; }
[Display(Name = "Phone")]
public string CT_PHONE_NUMBER { get; set; }
[Display(Name = "Ext")]
public string CT_PHONE_EXT { get; set; }
[Display(Name = "Fax")]
public string CT_FAX_NUMBER { get; set; }
[Display(Name = "Ext")]
public string CT_FAX_EXT { get; set; }
[Display(Name = "Assigned To")]
public string ASSIGNEE_USERNAME { get; set; }
[Display(Name = "Viewed Status")]
public string VIEWED { get; set; }
[Display(Name = "Territory")]
public string TERRITORY_CODE { get; set; }
[Display(Name = "Profile Class")]
public string PROFILE_CLASS_ID { get; set; }
[Display(Name = "Payment Terms")]
public string PAYMENT_TERMS_NAME { get; set; }
[Display(Name = "Payment Terms ID")]
public string PAYMENT_TERMS_ID { get; set; }
[Display(Name = "Profile Class")]
public string PROFILE_CLASS_NAME { get; set; }
[Display(Name = "Account Type")]
public string ACCOUNT_TYPE { get; set; }
public List<CurrencyList> currencyList { get; set; }
}
public class CurrencyList
{
public string CurrencyCode { get; set; }
public string CurrencyName { get; set; }
}
}
and the Action Method as below
public ActionResult Edit(int id)
{
CustomerDataAccessLayer customer = new CustomerDataAccessLayer();
Customer customer1 = new Customer {
currencyList = customer.GetAllCurrencies()
};
ModelState.Clear();
return View(customer.GetAllCustomers().Find(Customer => Customer.ID == id));
}
// POST: CustomerController/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id, IFormCollection collection)
{
try
{
return RedirectToAction(nameof(Index));
}
catch
{
return View();
}
}
I populate the List using a Data Access layer
public List<CurrencyList> GetAllCurrencies()
{
//throw new NotImplementedException();
List<CurrencyList> CurrenciesList = new List<CurrencyList>();
string Orasql = #"Select CURRENCY_CODE, DESCRIPTION CURRENCY_NAME, PRECISION DECIMAL_POINTS
from FND_CURRENCIES_VL where enabled_flag = 'Y'
ORDER BY 1";
OracleConnection conn = new OracleConnection(connectionString);
OracleCommand cmd = new OracleCommand(Orasql, conn);
//OracleDataReader dr = new OracleDataReader();
cmd.CommandType = CommandType.Text;
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataTable dt = new DataTable();
conn.Open();
da.Fill(dt);
conn.Close();
foreach (DataRow dr in dt.Rows)
{
CurrenciesList.Add(
new CurrencyList
{
CurrencyCode=Convert.ToString(dr["CURRENCY_CODE"]),
CurrencyName=Convert.ToString(dr["CURRENCY_NAME"])
}
);
}
return CurrenciesList;
}
Finally the view is like following:
#model ERPCustomerSupplier.Models.Customer
#{
ViewData["Title"] = "Edit";
Layout = "~/Views/Shared/_SiteMaster.cshtml";
}
<h1>Edit</h1>
<h4>Customer</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<table>
<tr>
<td>
<label asp-for="CURRENCY" class="control-label"></label>
</td>
<td>
<select asp-for="CURRENCY" class="form-control form-control-sm" asp-items="Model.currencyList" />
<span asp-validation-for="CURRENCY" class="text-danger"></span>
</td>
and I get the error error "CS0266: Cannot implicitly convert type 'System.Collections.Generic.List<ERPCustomerSupplier.Models.CurrencyList>' to 'System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem>'. An explicit conversion exists (are you missing a cast?)"
This is my 1st attempt with .Net Core & all helps are welcome.
The error message means you must use List SelectListItem rather than List CurrencyList,
you should use SelectListItem instead to generate a dropdownlist,following is a demo (database is sqlserver, you can change to yours):
public class Customer
{
[Display(Name = "ID")]
public int ID { get; set; }
[Display(Name = "Currency")]
public string CURRENCY { get; set; }
//....
[NotMapped] //add this
public List<SelectListItem> currencyList { get; set; } //change to SelectListItem
}
And I choose ViewBag to pass the selectListitem, it will be easier if you also want to
get the other properties in Customer Model:
public IActionResult Index()
{
//Fill data from database to currentList, and use ViewBag to pass.
ViewBag.currencyList = _context.CurrencyLists.Select(c => new SelectListItem { Value = c.CurrencyCode, Text = c.CurrencyName }).ToList();
return View();
}
View,and change the form too, your form will not show result:
<select asp-for="CURRENCY" class="form-control form-control-sm" asp-items="#(List<SelectListItem>)ViewBag.currencyList" >
<option>-Please select-</option>
</select>
Result:
Customer class modified from plain List item to List of SelectListItem
public List<SelectListItem> CurrencyList { get; set; }
List population modified with List object
public List<SelectListItem> GetAllCurrencies()
{
//throw new NotImplementedException();
List<SelectListItem> CurrencyList = new List<SelectListItem>();
string Orasql = #"Select CURRENCY_CODE, DESCRIPTION CURRENCY_NAME, PRECISION DECIMAL_POINTS
from FND_CURRENCIES_VL where enabled_flag = 'Y'
ORDER BY 1";
OracleConnection conn = new OracleConnection(connectionString);
OracleCommand cmd = new OracleCommand(Orasql, conn);
cmd.CommandType = CommandType.Text;
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataTable dt = new DataTable();
conn.Open();
da.Fill(dt);
conn.Close();
foreach (DataRow dr in dt.Rows)
{
CurrencyList.Add(new SelectListItem
{
Text = dr["CURRENCY_NAME"].ToString(),
Value = dr["CURRENCY_CODE"].ToString()
});
}
return CurrencyList;
}
Modified Edit action as below:
public ActionResult Edit(int id)
{
CustomerDataAccessLayer customerdataaccesslayer = new CustomerDataAccessLayer();
Customer customer1 = customerdataaccesslayer.GetCustomerData(id);
customer1.CurrencyList = customerDataAccessLayer.GetAllCurrencies();
ModelState.Clear();
//return View(customerdataaccesslayer.GetAllCustomers().Find(Customer => Customer.ID == id));
return View(customer1);
}
Modified Edit.cshtml like following:
<td>
<label asp-for="CURRENCY" class="control-label"></label>
</td>
<td>
<select asp-for="CURRENCY" class="form-control form-control-sm" asp-items="Model.CurrencyList"></select>
<span asp-validation-for="CURRENCY" class="text-danger"></span>
Hope this helps few others.

Why is my Viewmodel that I am returning to my POST method in MVC returning a null ViewModel

I really thought I understood what I was doing, but here goes. I decided I need more properties in my View so I created a ViewModel called ViewDataset and replaced the original Dataset model in the View. On my HttpGet TestDataset the View Model is populated correctly with data from the Viewmodel:
My original dataset that was working is below:
public class Dataset
{
public int Dataset_ID { get; set; }
public int Category_ID { get; set; }
public string Provider { get; set; }
public string Name { get; set; }
public string Institution { get; set; }
public string Description { get; set; }
public string Location { get; set; }
public bool Domestic { get; set; }
public bool International { get; set; }
public bool Includes_PHI { get; set; }
public bool PHI_Limited { get; set; }
public bool Includes_PIL { get; set; }
public bool PIL_Limited { get; set; }
public bool Citation_Requirements { get; set; }
public string Citation_Comments { get; set; }
public Nullable<System.DateTime> Availability_Beg_DT { get; set; }
public Nullable<System.DateTime> Availability_End_DT { get; set; }
public bool Subscription_Renewal { get; set; }
public Nullable<System.DateTime> Subscription_Renewal_DT { get; set; }
public bool Retention_Expiry { get; set; }
public Nullable<System.DateTime> Retention_Expiry_DT { get; set; }
public bool Data_Destruction { get; set; }
public Nullable<System.DateTime> Data_Destruction_DT { get; set; }
public string Data_Destruction_Instructions { get; set; }
public Nullable<int> Contract_ID { get; set; }
public bool Draft_Status { get; set; }
public bool Admin_Only { get; set; }
public string Dataset_Alias { get; set; }
public bool Loc_Amazon { get; set; }
public bool Loc_IT_Research { get; set; }
public bool Loc_Research_Proj { get; set; }
public bool Loc_Secure_Data { get; set; }
public bool Loc_Mercury { get; set; }
public bool Loc_Research_CC { get; set; }
public bool Loc_Research_VM { get; set; }
public bool Loc_External { get; set; }
public bool Access_Url { get; set; }
public bool Access_Download_App { get; set; }
public bool Access_Lab_Terminal { get; set; }
public bool Access_Email_Req { get; set; }
public bool Access_File_Download { get; set; }
public bool Access_Other { get; set; }
public string Location_Notes { get; set; }
public string Access_Notes { get; set; }
public Nullable<System.DateTime> Date_Added { get; set; }
public Nullable<System.DateTime> Date_Modified { get; set; }
public string Added_By_User { get; set; }
public string Updated_By_User { get; set; }
public bool External_Collaborators
{
get; set;
}
}
Here is my new ViewDataset (viewmodel)
public class ViewDataset
{
public Dataset dataset;
public List<SelectListItem> categories_list;
}
Here is my is a sample of my view ... couple of lines, but the view is populated correctly with data from the ViewDataset model
#model ResearchDataInventoryWeb.Models.ViewDataset
<td>
#Html.TextBoxFor(model => model.dataset.Institution, new { placeholder = "<Institution>", #class = "input-box" })
</td>
<td>
#Html.TextBoxFor(model => model.dataset.Name, new { placeholder = "<Dataset Name>", #class = "input-box" })
</td>
#Html.CheckBoxFor(model => model.dataset.Domestic) <span class="display-checkbox">Domestic</span>
#Html.CheckBoxFor(model => model.dataset.International) <span class="display-checkbox">International</span>
#Html.CheckBoxFor(model => model.dataset.Includes_PHI) <span class="display-checkbox">Includes PHI </span>
#Html.CheckBoxFor(model => model.dataset.Includes_PIL) <span class="display-checkbox">Includes PII </span><br />
#Html.CheckBoxFor(model => model.dataset.External_Collaborators) <span class="display-checkbox">External Collaborators Allowed (Sharable)</span>
#Html.CheckBoxFor(model => model.dataset.Citation_Requirements) <span class="display-checkbox">Citation Requirements</span>
<input type="submit" value="TestPost" />
Here is my HttpPost TestDataset : The model Viewdataset (dataset, categories_list) properties that I am passing back from the view are NULL, am I missing something?
[HttpPost]
public ActionResult TestDataset(ViewDataset viewdataset)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:4251/");
//HTTP POST
viewdataset.dataset.Category_ID = 2;
viewdataset.dataset.Dataset_ID = 1;
viewdataset.dataset.Location = "Fingers Crossed";
viewdataset.dataset.Institution = "Not Null";
var dataset = viewdataset.dataset;
// var postTask = client.PostAsJsonAsync<Dataset>("api/datasets/1", dataset);
var postTask = client.PostAsJsonAsync("api/datasets/1", dataset);
postTask.Wait();
var result = postTask.Result;
if (result.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
}
ModelState.AddModelError(string.Empty, "Server Error. Please contact administrator.");
return View(viewdataset);
}
Here if my HttpGet TestDataset in case you need to see it
public async Task<ActionResult> TestDataset()
{
//Hosted web API REST Service base url
string Baseurl = "http://localhost:4251/";
List<Dataset> dataset = new List<Dataset>();
List<Category> categories = new List<Category>();
var parm = "1";
var returned = new Dataset();
var ViewDataset = new ViewDataset();
using (var client = new HttpClient())
{
//Passing service base url
client.BaseAddress = new Uri(Baseurl);
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Sending request to find web api REST service resource GetAllEmployees using HttpClient
HttpResponseMessage Res = await client.GetAsync("api/Datasets/" + parm);
HttpResponseMessage Res2 = await client.GetAsync("api/Categories");
//Checking the response is successful or not which is sent using HttpClient
if (Res.IsSuccessStatusCode)
{
//Storing the response details recieved from web api
var EmpResponse = Res.Content.ReadAsStringAsync().Result;
//Deserializing the response recieved from web api and storing into the Employee list
returned = JsonConvert.DeserializeObject<Dataset>(EmpResponse);
}
if (Res2.IsSuccessStatusCode)
{
//Storing the response details recieved from web api
var CatResp = Res2.Content.ReadAsStringAsync().Result;
//Deserializing the response recieved from web api and storing into the Employee list
categories = JsonConvert.DeserializeObject<List<Category>>(CatResp);
}
// Create the Categories Select List
var categoryList = new List<SelectListItem>();
foreach (Category c in categories)
{
categoryList.Add(new SelectListItem
{
Value = c.Category_ID.ToString(),
Text = c.Description,
Selected = (c.Category_ID == returned.Category_ID ? true : false)
});
}
ViewDataset.dataset = returned;
ViewDataset.categories_list = categoryList;
//returned.External_Collaborators = returned.External_Collaborators == null || false ? false : true;
//returning the employee list to view
return View(ViewDataset);
}
}
Try to change
public class ViewDataset
{
public Dataset dataset;
public List<SelectListItem> categories_list;
}
to
public class ViewDataset
{
public Dataset dataset { get; set; }
public List<SelectListItem> categories_list { get; set; }
}

search function in ASP.NET MVC not working properly

i have a student table in my database that i created and i have a view that displays a list of all the students grouped by class... on top of the view i made a textbox and a search button to be able to access the student information faster. The problem is that i when i enter the first name and the last name in the textbox, nothing comes up. When i enter only the first name or only the last name, then it finds it. I'm new to programming and i can't figure out how to make it work. I would really appreciate if someone can help me with this. This is part of my code:
[HttpGet]
public ActionResult ViewStudents()
{
ViewBag.classes = db.Courses.ToList();
var studentCourses = db.StudentCourses.OrderBy(s=>s.Person.FirstName).ToList();
return View(studentCourses);
}
[HttpPost]
public ActionResult ViewStudents(string SearchString)
{
var student=new List<int>();
List<StudentCourse>sc=new List<StudentCourse>();
ViewBag.classes = db.Courses.ToList();
var studentCourse=db.StudentCourses.ToList();
var studentCourses = db.StudentCourses.OrderBy(s => s.Person.FirstName).ToList();
var substring = SearchString.IndexOf(" ").ToString();
if (!string.IsNullOrEmpty(SearchString))
{
student = (from p in db.People
where (p.FirstName.Contains(SearchString)) && (p.LastName.Contains(substring))||((p.FirstName.Contains(SearchString)) || (p.LastName.Contains(SearchString)))
select p.PersonId).ToList();
}
foreach (var s in studentCourse)
{
foreach (var i in student)
{
if (s.StudentId == i)
{
sc.Add(s);
}
}
}
return View(sc);
}
This is my view:
#model List<SchoolFinalProject.Models.StudentCourse>
#using (Html.BeginForm())
{
<div style="font-size:16px;"> <input type="text" id="search" placeholder="search" Name="SearchString" /><span class="glyphicon glyphicon-search"></span>
<input type="submit" value="search"></div>
}
#{
List<int> c = new List<int>();
foreach (var courses in ViewBag.classes)
{
foreach(var s in Model)
{
if(courses.CourseId==s.CourseId)
{
c.Add(courses.CourseId);
}
}
}
}
#foreach (var course in ViewBag.classes)
{
if(c.Contains(course.CourseId))
{
<h2>#course.Name<span>-</span>#course.Gender</h2>
<table class="table table-hover table-bordered table-striped">
<tr><th>First Name</th><th>Last Name</th><th>Email</th><th>Phone Number</th><th>Address</th><th>Date Of Birth</th></tr>
#foreach (var s in Model)
{
if(course.CourseId==s.CourseId)
{
<tr>
<td>#s.Person1.FirstName</td>
<td>#s.Person1.LastName</td>
<td>#s.Person1.Email</td>
<td>#s.Person1.PhoneNumber</td>
<td>#s.Person1.Address</td>
<td>#s.Person1.DateOfBirth</td>
<td>
<span class="glyphicon glyphicon-edit"></span>
#Html.ActionLink("Edit", "Edit","Person", new { id = s.Person1.PersonId }, null) |
<span class="glyphicon glyphicon-trash"></span>
#Html.ActionLink("Details", "Details","Person", new { id = s.Person1.PersonId }, null)
</td>
</tr>
}
}
</table>
}
}
Go to top of page
this is my person Model:
public partial class Person
{
public Person()
{
this.Bonus = new HashSet<Bonu>();
this.ConversationHistories = new HashSet<ConversationHistory>();
this.ConversationHistories1 = new HashSet<ConversationHistory>();
this.EmployeePaymentDetails = new HashSet<EmployeePaymentDetail>();
this.StudentCourses = new HashSet<StudentCourse>();
this.StudentCourses1 = new HashSet<StudentCourse>();
this.TeacherCourses = new HashSet<TeacherCourse>();
this.Reminders = new HashSet<Reminder>();
}
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Address { get; set; }
public Nullable<System.DateTime> DateOfBirth { get; set; }
public PersonType PersonTypeId { get; set; }
public Nullable<System.DateTime> LastModified { get; set; }
public Nullable<int> Gender { get; set; }
public Nullable<int> Status { get; set; }
public string FullName
{
get { return FirstName + ", " + LastName; }
}
public virtual ICollection<Bonu> Bonus { get; set; }
public virtual ICollection<ConversationHistory> ConversationHistories { get; set; }
public virtual ICollection<ConversationHistory> ConversationHistories1 { get; set; }
public virtual ICollection<EmployeePaymentDetail> EmployeePaymentDetails { get; set; }
public virtual ICollection<StudentCourse> StudentCourses { get; set; }
public virtual ICollection<StudentCourse> StudentCourses1 { get; set; }
public virtual ICollection<TeacherCourse> TeacherCourses { get; set; }
public virtual ICollection<Reminder> Reminders { get; set; }
}
}
You might want to try concatenating the first and last name properties in your person model like this:
[Display(Name = "Full Name")]
public string FullName
{
get
{
return LastName + ", " + FirstMidName;
}
}
There is a very good tutorial on what you are trying to do here: https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application
Also see this page of same tutorial: https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application
As an aside, you might want to check out using the Datatables plugin, which gives you search functionality without have to query your database with each search: https://datatables.net

Model evaluating to false while saving to database

So I have this problem when trying to save an item to the database in my asp.net mvc4 web app.
I have three classes listed below
public class Posts
{
[Key]
public int PostID { get; set; }
[Required(ErrorMessage="A Title is required for your Post")]
[Display(Name="Title")]
public string PostTitle { get; set; }
[Required(ErrorMessage="This Field is Required")]
[Display(Name = "Post")]
public string PostContent { get; set; }
[Required()]
[DataType(DataType.DateTime)]
public DateTime PostDate { get; set; }
//public int AuthorID { get; set; }
//public int CommentID { get; set; }
[NotMapped]
public virtual List<Comments> Comment { get; set; }
public virtual Users user { get; set; }
}
and this class has a many to one relationship with the users class below
public class Users
{
public Users()
{
}
[Key]
public int UserID { get; set; }
[Required()]
public string Firstname { get; set; }
[Required()]
public string Lastname { get; set; }
[Required()]
[DataType(DataType.Date, ErrorMessage="Enter a Valid Date")]
public DateTime DOB { get; set; }
//[Required()]
//public string Photo { get; set; }
[Required()]
public string Sex { get; set; }
[Required()]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
public DateTime RegDate { get; set; }
[Required()]
[Column("Username")]
//[Remote("doesUserNameExist", "Account", HttpMethod = "POST", ErrorMessage = "User name has already been taken. Please enter a different User name.")]
public string Username { get; set; }
[Required()]
[DataType(DataType.Password)]
public string Password { get; set; }
public string PasswordSalt { get; set; }
[System.ComponentModel.DataAnnotations.Compare("Password", ErrorMessage="Passwords do not match")]
[DataType(DataType.Password)]
//[NotMapped]
//public string ConfirmPassword { get; set; }
public virtual List<Posts> Post { get; set; }
public virtual List<Comments> Comment { get; set; }
}
The database table for the Posts.cs class has a field called user_UserID which i assume is to store the id of the user that creates a post. I'm trying to save the posts to the database using the below code
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Posts</legend>
<div class="form-group">
#Html.LabelFor(model => model.PostTitle)
#Html.TextBoxFor(model => model.PostTitle, new {#class = "form-control"})
#Html.ValidationMessageFor(model => model.PostTitle)
</div>
<div class="form-group">
#Html.LabelFor(model => model.PostContent)
#Html.TextAreaFor(model => model.PostContent, new {#class = "form-control"})
#Html.ValidationMessageFor(model => model.PostContent)
</div>
<input type="hidden" name="user.UserID" value="#Session["LoggedUserID"]" />
<div>
<input type="submit" value="Submit" />
</div>
</fieldset>
}
As you can see, the user ID i'm saving to the database table is gotten from the user ID stored in the Session["LoggedUserID"] variable. The controller that handles the saving is below
public class PostsController : Controller
{
//
// GET: /Posts/
BlogContext db = new BlogContext();
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Posts Post)
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
try
{
if (ModelState.IsValid)
{
var newPost = db.Post.Create();
newPost.PostTitle = Post.PostTitle;
newPost.PostContent = Post.PostContent;
newPost.PostDate = DateTime.Now;
newPost.user.UserID = Post.user.UserID;
db.Post.Add(newPost);
db.SaveChanges();
return RedirectToAction("Index", "Posts");
}
else
{
ModelState.AddModelError("", "Something is wrong with the model");
}
}
catch (NullReferenceException ex)
{
Debug.WriteLine("Processor Usage" + ex.Message);
}
return View();
}
}
I attached a breakpoint to the Modelstate.IsValid line and then debugged, but i noticed the ModelState is always evaluating to false and the ModelState.AddModelError is showing that is there is something wrong with validating the model. Ive tried all possible tweakings all to no avail. I need help. How can i save the Posts to the database table without this problem.
Please what am i doing wrong?
I suspect ModelState is invalid because you are posting a value for user.UserId (the hidden input) which is initializing the property User which is invalid because of the validation attributes applied to other properties of User. It would be better to create a view model for creating new Posts that contain only the properties you need to display/edit. It is not necessary to include a property for User (the author of the post) since this can be set in the controller when you save the data (similar to what you are doing for the PostDate property
View model
public class PostVM
{
[Required(ErrorMessage="A Title is required for your Post")]
[Display(Name="Title")]
public string Title { get; set; }
[Required(ErrorMessage="This Field is Required")]
[Display(Name = "Post")]
public string Content { get; set; }
}
Controller
[HttpGet]
public ActionResult Create()
{
PostVM model = new PostVM();
return View(model);
}
[HttpPost]
public ActionResult Create(PostVM model)
{
if(!ModelState.IsValid)
{
return View(model);
}
// Initialize new Posts
// Map properties from the view model, set the user and date
// Save and redirect
}
View
#model PostVM
#using (Html.BeginForm()) {
....
<div class="form-group">
#Html.LabelFor(model => model.Title)
#Html.TextBoxFor(model => model.Title, new {#class = "form-control"})
#Html.ValidationMessageFor(model => model.Title)
</div>
<div class="form-group">
#Html.LabelFor(model => model.Content)
#Html.TextAreaFor(model => model.Content, new {#class = "form-control"})
#Html.ValidationMessageFor(model => model.Content)
</div>
<input type="submit" value="Submit" />
}

Range Validation is not working

I have used range validation but this is not working. I am adding model,controller and view code.Please help(i have added only related fields only in this code).
Model is :
public class TicketDetailModel : TicketModelBase
{
public WorkOnTicketCreateModel WorkOnTicketCreateModel { get; set; }
}
public class TicketModelBase
{
[Required]
[Range(1, int.MaxValue, ErrorMessage = "Please enter a value bigger than {0}")]
public int EstimatedTime { get; set; }
public virtual List<WorkOnTicket> WorkOnTickets { get; set; }
}
public class WorkOnTicketCreateModel : WorkOnTicketModelBase
{
[Required]
[Display(Name = "AssignedToUser")]
public int AssignedToUserId { get; set; }
public IEnumerable<SelectListItem> AssignedUser { get; set; }
[Required]
[Display(Name = "Ticket Status")]
public int TicketStatusId { get; set; }
public TicketStatus TicketStatusVal { get; set; }
public IEnumerable<SelectListItem> TicketStatus { get; set; }
}
public class WorkOnTicketModelBase
{
public int Id { get; set; }
[Required]
public int EstimateHours { get; set; }
[Required]
[Range(1, int.MaxValue, ErrorMessage = "Please enter a value bigger than {0}")]
public int WorkedHours { get; set; }
}
Contoller:
[HttpPost]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Details(TicketDetailModel model, IEnumerable<HttpPostedFileBase> file)
{
using (ITransaction transaction = this.nhSession.BeginTransaction())
{
var ticketObj = this.nhSession.QueryOver<Ticket>().Where(t => t.Id == model.Id).SingleOrDefault();
var workOnTicket = new WorkOnTicket();
workOnTicket.Ticket = ticketObj;
workOnTicket.WorkedHours = model.WorkOnTicketCreateModel.WorkedHours;
workOnTicket.EstimateHours = model.WorkOnTicketCreateModel.EstimateHours;
ticketObj.WorkOnTickets.Add(workOnTicket);
this.nhSession.Save(ticketObj);
transaction.Commit();
}
return RedirectToAction("Details", new { id = model.Id, milestoneId = model.Milestone.Id, projectId = model.Project.Id });
}
View:-
#model AnkTech.TicketManagement.Web.Models.Ticket.TicketDetailModel
#using (Html.BeginForm("Details", "Ticket", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
#Html.TextBoxFor(model => model.WorkOnTicketCreateModel.EstimateHours, new { #id = "work_remaining", #class = "s-mini", size = "2" })
Worked hours: #Html.TextBoxFor(model => model.WorkOnTicketCreateModel.WorkedHours, new { #id = "worked_hours", #class = "s-mini", size = "2" })
<input type="submit" value="Submit" tabindex="2" name="commit" id="submit-comment"
class="gray-btn">
}
I have deleted all rmaining fields. i have added only fields to which related i am asking, please help.
You need to use ModelState.IsValid to check that the model is actually valid. Currently you assign validation attributes but never check them:
[HttpPost]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Details(TicketDetailModel model, IEnumerable file) {
if (!ModelState.IsValid)
{
// Handle error
}
else
{
using (ITransaction transaction = this.nhSession.BeginTransaction()) {
var ticketObj = this.nhSession.QueryOver<Ticket>().Where(t => t.Id == model.Id).SingleOrDefault();
var workOnTicket = new WorkOnTicket();
workOnTicket.Ticket = ticketObj;
workOnTicket.WorkedHours = model.WorkOnTicketCreateModel.WorkedHours;
workOnTicket.EstimateHours = model.WorkOnTicketCreateModel.EstimateHours;
ticketObj.WorkOnTickets.Add(workOnTicket);
this.nhSession.Save(ticketObj);
transaction.Commit();
}
}
return RedirectToAction("Details", new { id = model.Id, milestoneId = model.Milestone.Id, projectId = model.Project.Id });
}