Incorrect Models passed to View MVC C# error - c#

Can anyone help me correct the issue im having creating a view in MVC. Normally i just use Add/View and it scaffolds a view for me based upon my created method. The only problem is that this time i am creating a method to pass to view and i keep getting this error message
The model item passed into the dictionary is of type 'UserJob',
but this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable`1[UserJob]'.
The Methods i have written are the following...
public ActionResult AddJob(string userCode)
{
var jobs = jobsClient.GetAlljobs();
var alljobsCode = (from s in jobs select s.jobCode).ToList();
var usersJobs = (from s in db.UserJobs
where s.userCode == userCode
select s.jobCode).ToList();
var jobsNeeded = alljobsCode.Except(usersJobs);
List<UserJobsDTO> list = listBuilder(jobs, jobsNeeded);
ViewBag.jobCode = new SelectList(list, "jobCode", "jobDescription");
var model = new UserJob { userCode = userCode };
return View("AddJob", model);
}
private List<UserJobsDTO> listBuilder(
jobsService.jobsDTO[] jobs, IEnumerable<string> jobsNeeded)
{
List<UserJobsDTO> d = new List<UserJobsDTO>();
var f = jobsNeeded.ToArray();
var a = jobs.ToArray();
for (int i = 0; i < f.Length; i++)
{
d.Add(new UserJobsDTO()
{
jobCode = f.ElementAt(i),
description = a[i].jobDescription
});
}
return d;
}
When im debugging all of the required data is being passed to all the correct variable i am declaring, but the view just isnt playing ball. I was under the impression that scaffolding would automatically generate a useable View for me in Razor?? But this method just want play. Can anyone point me in the right direction??

Corrected version
public ActionResult AddJob(string userCode)
{
var jobs = jobsClient.GetAlljobs();
var alljobsCode = (from s in jobs select s.jobCode).ToList();
var usersJobs = (from s in db.UserJobs
where s.userCode == userCode
select s.jobCode).ToList();
var jobsNeeded = alljobsCode.Except(usersJobs);
List<UserJobsDTO> list = listBuilder(jobs, jobsNeeded);
ViewBag.jobCode = new SelectList(list, "jobCode", "jobDescription");
// var model = new UserJob { userCode = userCode };
return View("AddJob", usersJobs );
}
you will need to pass ienumarable here not an object type.
Update
#model IEnumerable<UserJobs>
foreach(var item in Model){
<span>#item.JobId</span>
<span>#item.JobName</span>
}

Related

How to add distinct value in database using Entity Framework

IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
}
}
db.SaveChanges();
I want to add only distinct values to database in above code. Kindly help me how to do it as I am not able to find any solution.
IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
var a = db.WebsiteWebPages.Where(i => i.WebPage == value.WebPage.ToString()).ToList();
if (a.Count == 0)
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
db.SaveChanges();
}
}
}
This is the code that I used to add distinct data.I hope it helps
In addition to the code sample Furkan Öztürk supplied, Make sure your DB has a constraint so that you cannot enter duplicate values in the column. Belt and braces approach.
I assume that by "distinct values" you mean "distinct value.WebPage values":
// get existing values (if you ever need this)
var existingWebPages = db.WebsiteWebPages.Select(v => v.WebPage);
// get your pages
var webPages = GetWebPages().Where(v => v.WebPage.Contains(".htm"));
// get distinct WebPage values except existing ones
var distinctWebPages = webPages.Select(v => v.WebPage).Distinct().Except(existingWebPages);
// create WebsiteWebPage objects
var websiteWebPages = distinctWebPages.Select(v =>
new WebsiteWebPage { WebPage = v, WebsiteId = websiteid});
// save all at once
db.WebsiteWebPages.AddRange(websiteWebPages);
db.SaveChanges();
Assuming that you need them to be unique by WebPage and WebSiteId
IEnumerable<WebsiteWebPage> data = GetWebPages();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
if (db.WebsiteWebPages.All(c=>c.WebPage != value.WebPage|| c.WebsiteId != websiteid))
{
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
db.WebsiteWebPages.Add(pagesinfo);
}
}
}
db.SaveChanges();
UPDATE
To optimize this (given that your table contains much more data than your current list), override your equals in WebsiteWebPage class to define your uniqueness criteria then:
var myWebsiteWebPages = data.select(x=> new WebsiteWebPage { WebPage = x.WebPage, WebsiteId = websiteid}).Distinct();
var duplicates = db.WebsiteWebPages.Where(x=> myWebsiteWebPage.Contains(x));
db.WebsiteWebPages.AddRange(myWebsiteWebPages.Where(x=> !duplicates.Contains(x)));
this is a one database query to retrieve ONLY duplicates and then removing them from the list
You can use the following code,
IEnumerable<WebsiteWebPage> data = GetWebPages();
var templist = new List<WebsiteWebPage>();
foreach (var value in data)
{
if (value.WebPage.Contains(".htm"))
{
WebsiteWebPage pagesinfo = new WebsiteWebPage();
pagesinfo.WebPage = value.WebPage;
pagesinfo.WebsiteId = websiteid;
templist.Add(pagesinfo);
}
}
var distinctList = templist.GroupBy(x => x.WebsiteId).Select(group => group.First()).ToList();
db.WebsiteWebPages.AddRange(distinctList);
db.SaveChanges();
Or you can use MoreLINQ here to filter distinct the list by parameter like,
var res = tempList.Distinct(x=>x.WebsiteId).ToList();
db.WebsiteWebPages.AddRange(res);
db.SaveChanges();

How to pass a list from method to another method

How to pass below action to another action in order to export it in excel sheet
,I need to pass VL list to another action
public ActionResult Details(int S)
{
SLMEntitiesDB dbContext = new SLMEntitiesDB();
var VL = (from U in dbContext.Users
join P in dbContext.Products
on U.PID equals P.PID
where P.PID == U.PID
select new UP()
{
UserO = U,
ProductO = P
}).Where(U => U.UserO.LID == S).ToList();
TempData["Exc"] = VL;
return View(VL);
}
and the other action within the same controller, but it's not working
public void ExportToExcel()
{
var V = TempData["Exc"] as List;
ExcelPackage pck = new ExcelPackage();
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Report");
ws.Cells["A1"].Value = "UserName";
int rowStart = 1;
foreach (var item in V)// here is the error
{
ws.Cells[string.Format("A{0}", rowStart)].Value = item.UserO.CN;
you'll create another Function\Action on your controller and pass the data from your view to it. Depending on the size of the data, you could do that as a QueryString (note: type .ToString() considerations, html encoding in that approach), but it's more likely you'll store the instance server-side, using TempData[key] or something similar.
The other aspect of what you're attempting to do (export an Excel File) will be handled by the added Action; However, instead of you handling the entire Response writing in the scope of your action, I recommend you define a type that inherits the FileResult type - where you handle HttpResponseBase in the overloaded WriteFile function (example below).
XLSFileResult
This sample type will actually be writing Comma Separate Value (CSV) content, but the Content-Type (coupled with Content-Disposition) will 'indicate' to the client that it is an excel file - the Response will respond with an ".xls" file.
Note: the filename and extension in this sample are actually defined at it's initialization - in the action of the controller.
public class XLSFileResult : FileResult
{
public XLSFileResult() : base(#"application/vnd.ms-excel")
{
Data = new List<UP>();
}
public IEnumerable<UP> Data { get; set; }
protected override void WriteFile(HttpResponseBase response)
{
// note: you'll want to handle this better; I'm just choosing a property of each complex type.
string[] lines = Data.Select(d => string.Join(", ", d.UserO.UserName , d.ProductO.PName)).ToArray();
byte[] buffer = response.ContentEncoding.GetBytes(string.Join(Environment.NewLine, lines));
response.BinaryWrite(buffer);
}
}
Sample Action\Function on the Controller
public ActionResult Details(int S)
{
SLMEntitiesDB dbContext = new SLMEntitiesDB();
var VL = (from U in dbContext.Users
join P in dbContext.Products
on U.PID equals P.PID
where P.PID == U.PID
select new UP()
{
UserO = U,
ProductO = P
}).Where(U => U.UserO.LID == S).ToList();
return View(VL);
}
protected FileResult HandleDataToFileResult(IEnumerable<UP> data)
{
return new XLSFileResult()
{
Data = data,
FileDownloadName = "MyFile.xls" //by virtue of this assignment, a 'Content-Disposition' Response.Header is added to HttpResponseBase
};
}
public FileResult GenerateFile()
{
var data = (IEnumerable<UP>)TempData["GenerateFile"];
return HandleDataToFileResult(data);
}
Razor Page
In this sample of the razor page, we'll use a ActionLink...
#using SLMDemo0.Models
#model IEnumerable<UP>
#{
ViewBag.Title = "Details";
//Review TempData, it's session data that clears at the end of the next request
TempData["GenerateFile"] = Model.ToArray();
}
...
#Html.ActionLink("GenerateFile", "GenerateFile");

LINQ Filtering Select Ouput with IEnumerable<T>

I have following methods:
Controller:
...
var appmap = Services.GetReqAppMapList(value);
var applist = Services.GetApplicationList(docid, appid, reqid, appmap);
...
Model:
public static IEnumerable<AppMap> GetReqAppMapList(int aiRequestTypeId)
{
try
{
var appmap = new List<AppMap>();
using (var eties = new eRequestsEntities())
{
appmap = (from ram in eties.ReqAppMaps
where ram.IsActive == 1
select new AppMap
{
RequestTypeId = ram.RequestTypeId
}).ToList();
return appmap;
}
}
catch(Exception e)
{
throw e;
}
}
public static IEnumerable<TicketApplication> GetApplicationList(int aiDocumentTypeId, int aiApplicationTypeId, int aiRequestTypeId, IEnumerable<AppMap> appmap)
{
try
{
var applicationlist = new List<TicketApplication>();
using (var applicationentity = new eRequestsEntities())
{
applicationlist = (from app in applicationentity.Applications
where 1==1
<<<Some Conditions Here???>>>
== && appmap.Contains(app.ApplicationTypeId) ==
&& app.IsActive == 1
select new TicketApplication
{
ApplicationId = app.ApplicationId,
Description = app.Description,
DeliveryGroupId = app.DeliveryGroupId,
ApplicationTypeId = app.ApplicationTypeId,
DeliveryTypeId = app.DeliveryTypeId,
DocumentTypeId = app.DocumentTypeId,
SupportGroupId = app.SupportGroupId
}).OrderBy(a => a.Description).ToList();
return applicationlist;
}
And I was thinking how can filter query result of GetApplicationList using the result from GetReqAppMapList
I'm kinda stuck with the fact that I must convert/cast something to the correct type because every time I do a result.Contains (appmap.Contains to be exact), I always get the following error
Error 4 Instance argument: cannot convert from
'System.Collections.Generic.IEnumerable<Test.Models.AppMap>' to
'System.Linq.ParallelQuery<int?>'
You should directly join the two tables in one query.
using (var applicationentity = new eRequestsEntities())
{
applicationlist = (from app in applicationentity.Applications
join ram in applicationentity.ReqAppMaps on app.ApplicationTypeId equals ram.RequestTypeId
where ram.IsActive == 1 && app.IsActive == 1
select new TicketApplication
{
ApplicationId = app.ApplicationId,
Description = app.Description,
DeliveryGroupId = app.DeliveryGroupId,
ApplicationTypeId = app.ApplicationTypeId,
DeliveryTypeId = app.DeliveryTypeId,
DocumentTypeId = app.DocumentTypeId,
SupportGroupId = app.SupportGroupId
}).OrderBy(a => a.Description).ToList();
You can delete the other method if it is not needed anymore. No point hanging onto code which is dead.
Looks like there is no other way to do this (as far as I know), so I have to refactor the code, I hope still that there would be a straight forward conversion and matching method in the future (too lazy). Anyway, please see below for my solution. Hope this helps someone with the same problem in the future. I'm not sure about the performance, but this should work for now.
Controller:
...
var appmap = Services.GetReqAppMapList(value);
var applist = Services.GetApplicationList(docid, appid, reqid, appmap);
...
Model:
<Removed GetReqAppMapList>--bad idea
public static IEnumerable<TicketApplication> GetApplicationList(int aiDocumentTypeId, int aiApplicationTypeId, int aiRequestTypeId)
{
try
{
//This is the magic potion...
List<int?> appmap = new List<int?>();
var applist = (from ram in applicationentity.ReqAppMaps
where ram.RequestTypeId == aiRequestTypeId
&& ram.IsActive == 1
select new AppMap
{
ApplicationTypeId = ram.ApplicationTypeId
}).ToList();
foreach (var item in applist)
{
appmap.Add(item.ApplicationTypeId);
}
//magic potion end
var applicationlist = new List<TicketApplication>();
using (var applicationentity = new eRequestsEntities())
{
applicationlist = (from app in applicationentity.Applications
where 1==1
===>>>&& appmap.Contains(app.ApplicationTypeId)<<<===
&& app.IsActive == 1
select new TicketApplication
{
ApplicationId = app.ApplicationId,
Description = app.Description,
DeliveryGroupId = app.DeliveryGroupId,
ApplicationTypeId =app.ApplicationTypeId,
DeliveryTypeId = app.DeliveryTypeId,
DocumentTypeId = app.DocumentTypeId,
SupportGroupId = app.SupportGroupId
}).OrderBy(a => a.Description).ToList();
return applicationlist;
}
A side-note, C# is a strongly-typed language, just make sure your data types matches during evaluation, as int? vs int etc.., will never compile. A small dose of LINQ is enough to send some newbies circling around for hours. One of my ID-10T programming experience but just enough to remind me that my feet's still flat on the ground.

Cannot implicitly convert type 'System.Linq.IQueryable?

here is my code which is giving me above error
public ActionResult Edit(int id = 0)
{
KBS_Virtual_TrainingEntities db = new KBS_Virtual_TrainingEntities();
UsersContext ctx = new UsersContext();
UserProfile model = ctx.UserProfiles.Find(id);
List<CourseSubscription> user_Course_subscriptions = new List<CourseSubscription>();
foreach (UserSubscription sub in db.UserSubscriptions)
{
if (sub.ID == id)
{
user_Course_subscriptions.Add(sub.CourseSubscription);
}
}
List<CourseSubscription> not_subscribe = db.CourseSubscriptions.Except(user_Course_subscriptions);
var coursesList = from courses in not_subscribe
select new SelectListItem
{
Text = courses.Course.Name,
Value = courses.Course.ID
.ToString()
};
var CoursesTYPE = from CourseTypes in db.CourseTypes.ToList()
select new SelectListItem
{
Text = CourseTypes.Name,
Value = CourseTypes.ID
.ToString()
};
ViewBag.CourseID = coursesList;
ViewBag.type = CoursesTYPE;
return View(model);
}
I am trying to find Course Subscription that are not subscribe by the current user by using the above code but its not working?
You're missing ToList on the results from your Except function. Do a ToList like so:
List<CourseSubscription> not_subscribe = db.CourseSubscriptions.Except(user_Course_subscriptions).ToList();
Or since in your code you're not doing anything that needs a list, simply var it or assign the correct type to it such as IQueryable<CourseSubscription> to it.
var not_subscribe = db.CourseSubscriptions.Except(user_Course_subscriptions);

Generic methods with entity framework

I have a question about using a generic method with the entity framework.
I am using this example model
Data Model
And this is the code in my webform this code to populate the object.
var user = new User();
var selectedTitles = new List<UserTitle>();
var selectedDisabilities = new List<UserDisability>();
var t = titleRepository.SearchFor(d => d.Id==1 || d.Id ==2);
foreach (var temp in t)
{
selectedTitles.Add(new UserTitle { IsPublic = true, Title = temp, User = user });
}
var ds = disabilityRepository.SearchFor(d => d.Id==1 || d.Id ==2);
foreach (var temp in ds)
{
selectedDisabilities.Add(new UserDisability { IsPublic = true, Disability = temp, User = user });
}
user.FirstName = "Johnathan";
user.LastName = "Rifkin";
user.UserTitles = selectedTitles;
user.UserDisabilities = selectedDisabilities;
userRepository.Insert(user);
As you can see when populating the “UserTitles” and “UserDisabilities” properties the code is very similar, so rather than duplicate the code I would like to create a generic method that I can use to populate both the “UserTitles” and “UserDisabilities” and any other properties that I'll need in future.
Thanks in advance

Categories