How to check an item is present in the Model - c#

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.

Related

How to bind 2 properties together in Razor Pages?

I'm building an application in Razor that supports the QA team in my company. The purpose is to reserve tests (called threads) to be executed by the team members. I'm new to programming and I've reached a problem i can't solve :(
OnGet - i get the list of the tests from the database (with the test names and testersIDs). I also get the list of testers from a different table and use that list to populate the drop-downs in the app (so i display the testers names instead of the testerIDs). It works fine.
OnPost - i would like to update the database when someone changes the drop-down values (either onChange or with a submit button). I've tried two options but neither of them works. I'll paste the code below but lets just assume for now that i have two testers in the DB: Id= 1, Name=Tester1 and Id=2, Name=Tetser2. I also have one test in another table that is assigned to the tester of Id=1. I want to change it to Id=2.
The model:
[BindProperty]
public List<Thread> Threads { get; set; }
[BindProperty]
public List<Tester> Testers { get; set; }
public int ThreadsCounter { get; set; }
public int TestersCounter { get; set; }
public void OnGet()
{
DataAccess db = new DataAccess();
Threads = db.GetThreads();
ThreadsCounter = Threads.Count;
Testers = db.GetTesters();
TestersCounter = Testers.Count;
}
public void OnPost()
{
DataAccess db = new DataAccess();
db.UpdateThread(Threads);
}
Option 1 (html select):
<div>
<table class="thread-table">
<thead>
<tr>
<th>Id</th>
<th>Test name</th>
<th>Data check tester</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < #Model.ThreadsCounter; i++)
{
<tr>
<td>#Model.Threads[i].Id</td>
<td>#Model.Threads[i].ThreadNumber</td>
<td>
<select name="dataTester-#i">
#if (Model.Threads[i].DataCheckTesterId == 0)
{
<option>--select--</option>
}
#for (int j = 0; j < #Model.TestersCounter; j++)
{
if (Model.Testers[j].Id == Model.Threads[i].DataCheckTesterId)
{
<option value="#Model.Testers[j].TesterName" selected>#Model.Testers[j].TesterName</option>
}
else
{
<option value="#Model.Testers[j].TesterName">#Model.Testers[j].TesterName</option>
}
}
</select>
</td>
</tr>
}
</tbody>
</table>
</div>
When use the drop-down to change the tester and i submit the form the value that is passed to Model.Threads[i].DataCheckTesterId (the tester's id) doesn't change. So if i want to change Tester1 to Tester2, i still pass the ID=1 and there is no change.
Option 2 (Html.DropDownList) - i know that this is the way to go, but the result is even worse so far:
<div>
<form method="post">
<table class="thread-table">
<thead>
<tr>
<th>Id</th>
<th>Test name</th>
<th>Data check tester</th>
</tr>
</thead>
<tbody>
#foreach (var thread in Model.Threads)
{
<tr>
<td>
<input type="hidden" name="Threads.Index" value="#thread.Id" />
<input type="hidden" name="Threads[#thread.Id].Id" value="#thread.Id" />
#thread.Id
</td>
<td>#thread.ThreadNumber</td>
<td>
<input type="hidden" name="Threads[#thread.DataCheckTesterId].Id" value="#thread.DataCheckTesterId" />
#Html.DropDownList("TestersList", new SelectList(Model.Testers, "Id", "TesterName", thread.DataCheckTesterId), "Select")
</td>
</tr>
}
</tbody>
</table>
<br />
<button>Update</button>
</form>
When i change the tester and submit, the value that is passed as Id = 0.
I've got all confused what is going on here but i suspect that this is caused by 2 properties (tests and testers) interfering with each other. I'd really appreciate a push in the right direction :)
I made some changes, you can refer to the below codes:
Model:
public class Thread
{
public int Id { get; set; }
public string ThreadName { get; set; }
public int DataCheckTesterId { get; set; }
}
public class Tester
{
public int Id { get; set; }
public string TesterName { get; set; }
}
View:
#{
var count = 0;
}
<form method="post">
<table class="thread-table">
<thead>
<tr>
<th>Id</th>
<th>Test name</th>
<th>Data check tester</th>
</tr>
</thead>
<tbody>
#foreach (var thread in Model.Threads)
{
<tr>
<td>
<input type="hidden" name="Threads[#count].Id" value="#thread.Id" />
#thread.Id
</td>
<td>
<input type="hidden" name="Threads[#count].ThreadName" value="#thread.ThreadName" />
#thread.ThreadName
</td>
<td>
#Html.DropDownList("Threads[" + count + "].DataCheckTesterId", new SelectList(Model.Testers, "Id", "TesterName", thread.DataCheckTesterId), "Select")
</td>
</tr>
count++;
}
</tbody>
</table>
<br />
<button>Update</button>
</form>
Controller:
[BindProperty]
public List<Thread> Threads { get; set; }
[BindProperty]
public List<Tester> Testers { get; set; }
public int ThreadsCounter { get; set; }
public int TestersCounter { get; set; }
public void OnGet()
{
Threads = new List<Thread>
{
new Thread{ Id = 1, ThreadName = "Tester1", DataCheckTesterId = 0},
new Thread{ Id = 2, ThreadName = "Tester2", DataCheckTesterId = 0},
new Thread{ Id = 3, ThreadName = "Tester3", DataCheckTesterId = 0},
};
Testers = new List<Tester>
{
new Tester{ Id = 1, TesterName = "AA"},
new Tester{ Id = 2, TesterName = "BB"},
new Tester{ Id = 3, TesterName = "CC"},
};
}
public void OnPost()
{
}
Result:

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>

ASP.NET MVC CRUD with LocalDb savechanges error

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>();
}

Trying to get the Selected checkbox values with the ID value

Below is the Model
public class M_ProjectType
{
public Int16 ProjectTypeID { get; set; }
public String ProjectType { get; set; }
public Boolean IsActive { get; set; }
public Decimal Cost { get; set; }
public String Description { get; set; }
public Boolean IsChecked { get; set; }
}
Below is View Model
public class VM_Project
{
public string[] SkillID { get; set; }
public List<M_ProjectType> ProjectType { get; set; }
}
Below is Get Action method. here I am getting the data for projects that will be sent to View Model
[HttpGet, Route("Project")]
public async Task<ActionResult> Project()
{
var projectTypes = (await _projectTypes.ProjectTypesList()).Value;
var list = new List<M_ProjectType>();
foreach (var item in projectTypes)
{
list.Add(new M_ProjectType
{
Cost = item.Cost,
Description = item.Description,
IsActive = item.IsActive,
IsChecked = false,
ProjectType = item.ProjectType,
ProjectTypeID = item.ProjectTypeID
}
);
}
var project = new VM_Project
{
ProjectType = list
};
return View(project);
}
Below is Razor View
#foreach (var item in Model.ProjectType)
{
<table class="table table-striped">
<tbody>
<input type="hidden" value="#item.ProjectTypeID" name="ProjectTypeID" />
<tr>
<td style="width:5%">
#Html.CheckBoxFor(i => item.IsChecked, new { #class = "tableflat" })
#Html.HiddenFor(i => item.ProjectTypeID)
</td>
<td style="width:10%">#item.ProjectType</td>
<td style="width:80%">#item.Description</td>
<td style="width:5%"><b>$#item.Cost</b></td>
</tr>
</tbody>
</table>
}
Below is Post Action Method
[HttpPost, Route("Project")]
public ActionResult Project(VM_Project project)
{
return View();
}
Question: I am getting project.ProjectType = null. Any suggestion why
this is happening ?
I would recommend using EditorTemplates.
Create a folder named EditorTemplates in you Views/Shared direcotry.
Create a partial view based on your type i.e. M_ProjectType.cshtml
Put your markup that you use in foreach loop in M_ProjectType.cshtml file
#model M_ProjectType
<table class="table table-striped">
<tbody>
<tr>
<td style="width:5%">
#Html.CheckBoxFor(i => i.IsChecked, new { #class = "tableflat" })
#Html.HiddenFor(i => i.ProjectTypeID)
</td>
<td style="width:10%">#Model.ProjectType
#Html.HiddenFor(i=>i.ProjectType)
</td>
<td style="width:80%">#Model.Description</td>
<td style="width:5%"><b>$#Model.Cost</b></td>
</tr>
</tbody>
Then render your editor template in your form like (note: no foreach loop)
#Html.EditorFor(m=>m.ProjectType)
You should get correct model binded to your html elements back in controller.
Try this:
#foreach (var item in Model.ProjectType)
{
<table class="table table-striped">
<tbody>
<tr>
<td style="width:5%">
#Html.CheckBoxFor(i => item.IsChecked, new { #class = "tableflat" })
#Html.HiddenFor(i => item.ProjectTypeID, new { #Value = item.ProjectTypeID})
</td>
</tr>
</tbody>
</table>
}

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.

Categories

Resources