ASP.NET MVC CRUD with LocalDb savechanges error - c#

I'm using VS 2015 and I created an ASP.NET MVC project and added a couple things (log in and register did work fine with Localdb called MyDatabase.mdf) that did work.
CRUD only create function in db the rest will come later.
But now I can't get this work. Inside the LocalDb called MyDatabase.mdf, I have created another table called Amsterdam:
[MyDatabase.mdf][1]
And this is my MainDbContext.cs - here I added
public DbSet<Amsterdam> Amsterdam { get; set; }
And in my Home folder I wrote Amsterdam.cshtml like this:
#model IEnumerable<MyFirstWebsite.Models.Amsterdam>
#{
ViewBag.Title = "Amsterdam";
var username = User.Identity.Name;
}
<h2>#username's Bestellijst Amsterdam</h2>
#using (Html.BeginForm())
{
<span>Enter new item: </span>
<br/>
<input type="text" name="new_item"/>
<br/>
<span>Public post?</span>
<input type="checkbox" name="check_public"/><br/>
<br/>
<input type="submit" value="Add Item"/>
}
<br/>
<table class="table table-bordered table-condensed">
<thead>
<tr>
<th style="text-align: center;">Id Bestelling</th>
<th style="text-align: center;">Details Bestelling</th>
<th style="text-align: center;">Time - Ontvangen Bestelling</th>
<th style="text-align: center;">Time - Verzonden Bestelling</th>
<th style="text-align: center;">Edit</th>
<th style="text-align: center;">Delete</th>
<th style="text-align: center;">Public Post</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;"></td>
<td style="text-align: center;">
Edit
</td>
<td style="text-align: center;">
Edit
</td>
<td style="text-align: center;"></td>
</tr>
</tbody>
</table>
And in my Models folder I created Amsterdam.cs which looks like this:
namespace MyFirstWebsite.Models
{
public class Amsterdam
{
[Key]
public int Id { get; set; }
public string Details { get; set; }
public string Date_Posted { get; set; }
public string Time_Posted { get; set; }
public string Date_Edited { get; set; }
public string Time_Edited { get; set; }
public string Public { get; set; }
public int User_Id { get; set; }
}
}
And in my Controllers folder my HomeController looks like this:
public ActionResult Amsterdam()
{
return View();
}
[HttpPost]
public ActionResult Amsterdam(Amsterdam list)
{
string timeToday = DateTime.Now.ToString("h:mm:ss tt");
string dateToday = DateTime.Now.ToString("M/dd/yyyy");
if (ModelState.IsValid)
{
using (var db = new MainDbContext())
{
Claim sessionEmail = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email);
string userEmail = sessionEmail.Value;
var userIdQuery = db.Users.Where(u => u.Email == userEmail).Select(u => u.Id);
var userId = userIdQuery.ToList();
var dbAmsterdam = db.Amsterdam.Create();
dbAmsterdam.Details = list.Details;
dbAmsterdam.Date_Posted = dateToday;
dbAmsterdam.Time_Posted = timeToday;
dbAmsterdam.User_Id = userId[0];
db.Amsterdam.Add(dbAmsterdam);
db.SaveChanges();
}
}
else
{
ModelState.AddModelError("", "Incorrect format has been placed");
}
return View();
}
I know I got close because my register does work but I can't get my CRUD for Amsterdam to work. When I click ok as shown in the screenshot (when I click on Ad Item):
https://i.stack.imgur.com/XsGws.png
I get an error
DbUpdateException was unhandled by user code
https://i.stack.imgur.com/I6kYP.png

It appears that EF is doing pluralization of your object name to define the table name in the database (from the error - Invalid object name dbo.Amsterdams).
If your table name is Amsterdam (singular, without the trailing "s"), then add this data annotation to your model class:
[Table("Amsterdam")]
public class Amsterdam
{
[Key]
public int Id { get; set; }
.....
}
And if you want to turn off that pluralization of table names completely, you can add this line to your MainDbContext class:
protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
{
dbModelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}

Related

Serveral models in one view ASP.net core with EF core

I want to create a Dashboard of two tables and a chart of data in the database using ASP.net Core 3.1 and EF Core 3.
This the teacher model class:
public class Teacher
{
[Key]
public Int64 ID { get; set; }
public Sring Name { get; set; }
public int Age { get; set; }
}
this is the course model class :
public class Course
{
[Key]
public Int64 ID { get; set; }
public Sring Name { get; set; }
public Sring TargetClass { get; set; }
}
The ViewModel class is as follows:
public class DashboardViewModel
{
public List<Course> Course { get; set; }
public List<Teacher> Teacher { get; set; }
}
the index page is :
<h2> Table of Teacher</h2>
<table>
<thead>
<tr>
<th> ID</th>
<th> Name</th>
<th> Age</th>
</tr>
</thead>
<tbody>
#foreach (Teacher item in Model.Teacher)
{
<tr>
<td>
#item.ID
</td>
<td>
#item.Name
</td>
<td>
#item.Age
</td>
</tr>
}
</tbody>
</table>
<h2> Table of Courses</h2>
<table>
<thead>
<tr>
<th> ID</th>
<th> Name</th>
<th> TargetClass</th>
</tr>
</thead>
<tbody>
#foreach (Teacher item in Model.Course)
{
<tr>
<td>
#item.ID
</td>
<td>
#item.Name
</td>
<td>
#item.TargetClass
</td>
</tr>
}
</tbody>
</table>
The home controller is :
public class HomeController : Controller
{
private readonly ApplicationDbContext _context;
public HomeController(ApplicationDbContext context)
{
_context = context;
}
public async Task<IActionResult> Index()
{
var qry = await _context.Teacher.ToListAsync();
var Teachers = new List<Teacher>(){};
var Courses = new List<Courses>() { };
var Dash = new DashboardViewModel {
Course = Courses,
Teacher = Teachers
};
return View(Dash);
}
The Problem appears when trying to pass the data from qry variable to list.
Question : How I can pass the data from EF to List of Teachers as the example?
var qry = _context.Teacher.ToListAsync();
var Teachers = new List<Teacher>(){qry};
Without convert error :
cannot convert from 'System.Threading.Tasks.Task<System.Collections.Generic.List<School.Models.Teacher>>' to 'School.Models.Teacher'
I can't do this in comments, so I will put this here and then I can amend the answer if it's not quite right. You don't need to create empty lists beforehand, just create the ViewModel all in one shot. As I think jegtugado was trying to suggest, the Index() code should look something like:
public async Task<IActionResult> Index()
{
var Dash = new DashboardViewModel {
Course = await _context.Course.ToListAsync(),
Teacher = await _context.Teacher.ToListAsync()
};
return View(Dash);
}
This is assuming your DbSets are called Teacher and Course (but these are often plural, so double check that).

How to return multiple viewbag data to view from controller?

I am using weather API in which user search weather for specific City or Country from view which is receive by controller as parameter,information about weather is completely working but I am just unable to return all that information back to view from controller.
view for search
<form action="searchbyname" method="post">
<input type="text" name="weather" placeholder="Find your location...">
<input type="submit" value="Find">
</form>
Controller
public ActionResult searchbyname(string weather)
{
string appId = "f40a39abac667183c127adefffcf88ed";
string url = string.Format("http://api.openweathermap.org/data/2.5/weather?q={0}&units=metric&APPID={1}", weather, appId);
using (WebClient client = new WebClient())
{
string json = client.DownloadString(url);
if (json.IndexOf("Error") == -1)
{
WeatherInfo weatherInfo = (new JavaScriptSerializer()).Deserialize<WeatherInfo>(json);
ViewBag.citycountry = weatherInfo.name + "," + weatherInfo.sys.country;
ViewBag.ImageUrl = string.Format("http://openweathermap.org/images/flags/{0}.png", weatherInfo.sys.country.ToLower());
ViewBag.des = weatherInfo.weather[0].description;
//weatherimage
ViewBag.ImageUrl = string.Format("http://openweathermap.org/img/w/{0}.png", weatherInfo.weather[0].icon);
ViewBag.temp = string.Format("{0}°С", Math.Round(weatherInfo.main.temp, 1));
}
}
return View();
}
View in which data should be shown
<table id="tblWeather" border="0" cellpadding="0" cellspacing="0" style="display:none">
<tr>
<th colspan="2">
Weather Information
</th>
</tr>
<tr>
<td rowspan="3">
<img id="imgWeatherIcon" />
</td>
</tr>
<tr>
<td>
<span id="citycountry">#ViewBag.citycountry</span>
<img id="imageurl" src="#ViewBag.ImageUrl" />
<span id="des">#ViewBag.des</span>
</td>
</tr>
Model class
public class ClimateModel
{
public class WeatherInfo
{
public Coord coord { get; set; }
public Sys sys { get; set; }
public List<Weather> weather { get; set; }
public Main main { get; set; }
public int dt { get; set; }
public string name { get; set; }
}
public class Coord
{
public double lon { get; set; }
public double lat { get; set; }
}
public class Sys
{
public string country { get; set; }
}
public class Weather
{
public string main { get; set; }
public string description { get; set; }
public string icon { get; set; }
}
public class Main
{
public double temp { get; set; }
public double temp_min { get; set; }
public double temp_max { get; set; }
public int humidity { get; set; }
}
}
}
I think you are mixing some concepts between WebForms and MVC. There is no runat="server", asp:Label or asp:Image on MVC. You must use with pure HTML elements.
Your code should looke like:
<table id="tblWeather" border="0" cellpadding="0" cellspacing="0" style="display:none">
<tr>
<th colspan="2">
Weather Information
</th>
</tr>
<tr>
<td rowspan="3">
<img id="imgWeatherIcon" />
</td>
</tr>
<tr>
<td>
<span id="citycountry">#ViewBag.citycountry</span>
<img id="imageurl" src="#ViewBag.ImageUrl" />
<span id="des">#ViewBag.des</span>
</td>
</tr>
</table>
EDIT 1: As #erik-philips pointed out, you should really create a model class.
EDIT 2: Take a look at HTML Helpers. The can make your life easier when binding models to views.
As Erik pointed out in his comment you could use a model to capture the api response, and then put it either in a viewbag, or a viewdata to be able to access it inside the view .
ViewBag.WeatherInfo = weatherInfo;
Then inside your view you can do :
var weatherInfo = ViewBag.WeatherInfo as WeatherInfo
This way you have access to your object inside the view
As requested here is how it can be used in your situation
#{
var weatherInfo = ViewBag.WeatherInfo as WeatherInfo
}
<table id="tblWeather" border="0" cellpadding="0" cellspacing="0" style="display:none">
<tr>
<th colspan="2">
Weather Information
</th>
</tr>
<tr>
<td rowspan="3">
<img id="imgWeatherIcon" />
</td>
</tr>
<tr>
<td>
<span id="citycountry">#weatherInfo.name , #weatherInfo.sys.country</span>
<img id="imageurl" src="your image link" />
<span id="des">#weatherInfo.weather.First().description</span>
</td>
</tr>

How to check an item is present in the Model

My controller code looks like below
[HttpPost]
public string Rating(int id, int rate, double avgrating)
{
rating rating = new rating();
rating.date = DateTime.Now;
rating.trendid = id;
rating.rating1 = rate;
rating.ratedby = User.Identity.Name;
db.ratings.Add(rating);
db.SaveChanges();
return "{\"error\":false}";
}
In the view I have written a code as below
#using (Html.BeginForm("Rating", "Article"))
{
<h4>Please Rate the Article</h4>
<table id="temp" class: "table" cellspacing="0" cellpadding="7.5" style="text-align:center">
<tbody>
<tr class="rowc">
<td class="col1 cel1">Please Obselete</td>
<td class="col2 cel1">Not Very Useful</td>
<td class="col3 cel1">Helpful</td>
<td class="col4 cel1">Useful</td>
<td class="col5 cel1">Excellent</td>
</tr>
<tr class="rowb">
<td class="col1 cel1">
#Html.RadioButton("rate","1")
</td>
<td class="col2 cel1">
#Html.RadioButton("rate","2")
</td>
<td class="col3 cel1">
#Html.RadioButton("rate","3")
</td>
<td class="col4 cel1">
#Html.RadioButton("rate","4")
</td>
<td class="col5 cel1">
#Html.RadioButton("rate","5")
</td>
</tr>
</tbody>
</table>
#Html.HiddenFor(m => Model.id);
<button type="submit" class="btn btn-primary">Rate!</button>
}
Now the part I don't understand is I have a rating saved as below in the code
#{
double rating = 0;
double count = 0;
if (Model.ratings.Select(r => r.rating1).Count() > 0)
{
rating = Model.ratings.Select(r => r.rating1).Average();
count = Model.ratings.Select(r => r.rating1).Count();
}
}
my rating.cs looks like below
namespace SVMD.Models
{
using System;
using System.Collections.Generic;
public partial class rating
{
public int id { get; set; }
public System.DateTime date { get; set; }
public int trendid { get; set; }
public int rating1 { get; set; }
public string ratedby { get; set; }
public virtual trend trend { get; set; }
}
}
The questions I have is
How do I pass rating populated as Model.ratings.Select(r =>
r.rating1).Count(); to the controller to populate avgrating?
I want to show the rating tab only if the current user is not
present in ratedby list. I'm not sure how to accomplish that.

Trouble passing data from database table to view

I am filling an SQL table with a query and then trying to pass the data from the model (for the table) into the view. I am attempting to use a ViewModel to pass the data to the view in a Controller Action.
Here is the Model:
public partial class Report
{
public int Id { get; set; }
public string Number { get; set; }
public Nullable<decimal> Amount { get; set; }
public Nullable<System.DateTime> Date { get; set; }
public Nullable<int> ReasonId { get; set; }
public string Notes { get; set; }
}
IEnumerable ViewModel:
public class ReportViewModel
{
public IEnumerable<Report> Reports { get; set; }
}
Controller Action:
[HttpPost]
public ActionResult UploadValidationTable(HttpPostedFileBase csvFile)
{
//Unrelated Code to read a CSV into another database table goes here
//But was removed so it wouldn't be confusing.
var db = new Report();
var reportModel = new ReportViewModel()
{
Reports = new List<Report>() {new Report()}
};
return View("Upload", reportModel);
}
View:
#model Entities.Models.ReportViewModel
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Number</th>
<th>Amount</th>
<th>Date</th>
<th>Reason Id</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
foreach (var item in Model.Reports.Where(x => x.Id != null))
{
<tr>
<td>
#item.Id
</td>
<td>
#item.Number
</td>
<td>
#item.Amount
</td>
<td>
#item.Date
</td>
<td>
#item.ReasonId
</td>
<td>
#item.Notes
</td>
</tr>
}
}
</tbody>
</table>
But I get an exception when I try to return the View which says ReportViewModel is not assignable to model type IEnumerable ReportViewModel
So I am just trying to pass all the rows from the Report database to an HTML table in my view. Any help, or a better way to do this would be appreciated.

Model not getting bound to the view in asp.net MVC

I am trying to display a list of Providers in a table.The code to get the list of providers is as follows
public ActionResult Index()
{
DAL2 dal = new DAL2();
Provider patientlist = new Provider();
List<Provider> providers = dal.GetListofProviders.ToList();
return View(providers);
}
The above code is working fine.I am getting the list of providers as expected.
The HTML code in the view is as follows
#model IEnumerable<ProviderDemo.Models.Provider>
#{
ViewBag.Title = "ProviderList";
}
<head>
<title>LIST OF PROVIDERS</title>
</head>
<body>
<table class="table table-striped table-bordered table-hover">
<tr>
<th>Provider Type</th>
<th>First Name</th>
<th>Last Name</th>
<th>Certification</th>
<th>Specialization</th>
<th>SSN</th>
<th>Facility Name</th>
<th>Contact No</th>
<th>Contact Email</th>
<th></th>
</tr>
<tbody data-bind="foreach: viewmodel">
<tr>
<td class="col-lg-2" data-bind="text: ProviderType"></td>
<td class="col-lg-1" data-bind="text: FirstName"></td>
<td class="col-lg-1" data-bind="text: LastName"></td>
<td class="col-lg-1" data-bind="text: Certification"></>
<td class="col-lg-1" data-bind="text: Specialization"></td>
<td class="col-lg-1" data-bind="text: SSN"></td>
<td class="col-lg-4" data-bind="text: FacilityName"></td>
<td class="col-lg-4" data-bind="text: ContactNumber"></td>
<td class="col-lg-1" data-bind="text: ContactEmail"></td>
<td><a class="btn btn-default" id="del" onclick = "return confirm('Are you sure, you want to delete');" data-bind="attr: { href: '/ProviderRegister/Delete/' + ProviderID }"> Delete </a>
</td>
</tr>
</tbody>
</table>
</body>
My Provider class is as follows:
public class Provider
{
public int ProviderID { get; set; }
public string ProviderType { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Certification { get; set; }
public string Specialization { get; set; }
public string SSN { get; set; }
public string ContactNumber { get; set; }
public string ContactEmail { get; set; }
public string FacilityName { get; set; }
}
Provider Viewmodel
var Provider =
{
ProviderID:ko.observable(""),
ProviderType: ko.observable(""),
FirstName: ko.observable(""),
LastName: ko.observable(""),
Certification: ko.observable(""),
Specialization: ko.observable(""),
SSN: ko.observable(""),
ContactNumber: ko.observable(""),
ContactEmail: ko.observable(""),
FacilityName: ko.observable(""),
}
ko.applyBindings(Provider);
The list is not getting displayed in the table.There seems to be an error at the top of the html for the model.I dont understand why though.Am I doing something wrong here?Please guide me in the right direction.
Thanks a lot for all your help guys,but I made a mistake earlier.In the Index action ,I see the list of providers but I dont get any data in the view.So,I have the data in the controller but not in the view.
If you have a populated Model, you need to get the data from that out into you knockout model. So either use System.Web.Helpers.Json.Encode() or make your own JSON in the view.
Then load that data into your knockout view model.
var data = #Json.Encode(Model);
var ViewModel = function(data) {
var self = this;
self.Providers = ko.observableArray(data);
};
var viewmodel = new ViewModel(data);
ko.applyBindings(viewmodel);
and then in your foreach, use Providers instead of viewmodel

Categories

Resources