I have three objects:
public class Part
{
[Key]
public int ID { get; set; }
public string Number { get; set; }
public string Name { get; set; }
public int descID { get; set; }
}
public class Description
{
[Key]
public int descID { get; set; }
public string descName { get; set; }
public string description { get; set; }
}
public class GridPart
{
public string name{ get; set; }
public string number { get; set; }
public string description { get; set; }
}
I'm using LINQ to join Part and Description on the descID column:
public ActionResult Index()
{
var myParts = from p in db.Parts
join d in db.Description on p.descID equals d.DescriptorID
select new { Description = d.description, Name = p.name};
List<GridPart> partsList = new List<GridPart>();
foreach (var m in myParts)
{
GridPart gp = new GridPart();
gp.Name = m.name;
gp.description = m.description;
partsList.Add(gp);
}
return View(partsList);
}
If I was just using the Parts table, in the view I would do:
#model IEnumerable<MyApp.Models.Part>
What do I do if I'm using the joined table? This uses both Parts and Description, not to mention my List of GridParts, how do I pass this through to display all of the data I need?
Any advice is greatly appreciated.
If you pass an anonymous type to your view it won't be strongly typed. You can refer to your model like this instead
#Html.TextBox("Name")
or
#Html.Display("Name")
Although this will work I would advice against it - The better solution would be to go with a Viewmodel instead. This will make your view strongly typed.
Edit: Looking on this again I see that your actually not parsing the anonymous type to your view. Your parsing a list of GridParts.
You should be able to strongly type your view like your tried - just refer to GridParts instead of parts.
#model IEnumerable<MyApp.Models.GridPart>
Related
I have a model linked to a second table:
public class Rock
{
public int ID { get; set; }
[ForeignKey("Con")]
public int ConID { get; set; }
public virtual Con Con { get; set; }
}
public class Con
{
public int ID { get; set; }
public virtual ICollection<Rock> Rock{ get; set; }
[Required]
[RegularExpression(#"^[0-9A-Za-z '']+$")]
[StringLength(200, MinimumLength = 3)]
public string Name { get; set; }
}
In my control, I have a 'create' action:
// GET: Rock/Create/3337
[Route("Rock/Create/{ConID?}")]
public ActionResult Create(int? ConID)
{
var rock= new Rock();
rock.ConID = (int)ConID;
return View(rock);
}
I'd like to get the con name from that table and send it to the view. At this point it doesn't know the name because there's no 'rock' record linking it yet.
Any suggestions? Thanks in advance!
If you have created a strongly typed view with Rock as Type, you need to either add 'Con Name' property to Rock Type or else you need to create a new Type and add the data to this Type which you want to pass to the View.
public class NewType
{
public int ConID { get; set; }
public string ConName { get; set; }
}
Add the data you want to pass in this Type and return view with this object:-
public ActionResult Create(int? ConID)
{
var newType= new NewType();
newType.ConID = (int)ConID;
newType.ConName = "XYZ";
return View(newType);
}
The two suggestions I would give are to pass Con.name to the view in the viewbag or to create a viewmodel, as Rahul suggested, that combines the properties of different classes that are needed for that particular view.
I'm making a simple website where I'm storing some information that I get from an excel file into my models class and retrieving them from the html page. The following class is a class in my models:
public class ToxinInformation
{
public string cas_rn { get; set; }
public string critical_effect { get; set; }
public string point_of_departure { get; set; }
public string adi_tdi { get; set; }
public string intake { get; set; }
public string hazard_quotient { get; set; }
public string comment { get; set; }
public string tox_link { get; set; }
public string tox_link_decription { get; set; }
public string intake_link { get; set; }
public string intake_link_description { get; set; }
public IList<string> Links { get; set; }
}
And I use this code to set the information in my controller class and return the view:
(of course I would set information all the variables, not only the first one)
var model = new ToxinInformation
{
cas_rn = "lol"
};
return View(model);
So far I can easily set all my strings and my list and retrieve them on my html page, but what do I do if in some cases I need several instances of the class "ToxinInformation"? In some cases I have 2 or more set of data I'd like to save and show in HTML except for just one.
Any suggestions would be very helpful.
You should make a list and add instances of model to the list. Then you can use a DisplayFor or EditorFor template to show them all.
var models = new List<ToxinInformation>();
foreach(var dataBlob in YourDataStore)
{
var model = new ToxinInformation()
{
cas_rn = dataBlob.cas_rn // Not sure where your raw data is coming from.
}
models.add(model)
}
return View(models);
I am trying to bind a tree view menu control in a partialview with the ViewModel.
I have created a nested viewModel assuming that is the rightway to carry all the nested data needed for the navigation tree menu at one time and so I have wrote my linq query to fetch the data in a nested fashion. As newbie I am not 100% sure that this is the right way to do it.
I am trying to bind my view model with Linq query result. My Model is nested and so is my Linq query. I am facing difficulty molding this two together. What ever way I try I am getting type casting error such as cannot convert from Type IQueriable to IList of collections.. My code:
// ViewModel
namespace My.Namespace
{
public class MyViewModel
{
public decimal CategoryID { get; set; }
public string CategoryName { get; set; }
public decimal Badge { get; set; }
public IList<SubCategories> CategorySubCategories { get; set; }
}
public class SubCategories
{
public decimal SubCategoryID { get; set; }
public string SubCategoryName { get; set; }
public decimal Badge { get; set; }
public List<Items> SubCategoryItems { get; set; }
}
public class Items
{
public decimal ID { get; set; }
public string ItemName { get; set; }
public List<SubItems> SubItems { get; set; }
}
public class SubItems
{
public decimal ID { get; set; }
public string SubItemName { get; set; }
}
}
//Databinding code:
MyViewModel result = new MyViewModel();
var query= (List<MyViewModel>)(from c in dbContext.TableName
where c.CHILD_ID == 0
select new MyViewModel
{
CategoryID = c.ELEMENT_ID,
CategoryName = c.CHILD_DESC,
CategorySubCategories = (List<SubCategories>)(from s in dbContext.TableName
where s.PARENT_ID == c.ELEMENT_ID
select new SubCategories
{
SubCategoryID = s.ELEMENT_ID,
SubCategoryName = s.CHILD_DESC,
SubCategoryItems = (List<Items>)(from i in dbContext.TableName
where i.PARENT_ID == s.ELEMENT_ID
select new Items
{
ID = i.ELEMENT_ID,
ItemName = i.CHILD_DESC
}
)
}
)
});
return query.toList();
The error I am getting is # line: var query = (List)(from c in dbContext.TableName
Error:
Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery1[MyViewModel]' to type 'System.Collections.Generic.List1[MyViewModel]'.
On your view model, change your List types to IEnumerable types. Make sure not to use the .ToList() extension method on those sub selects.
The resulting types of your sub select statements are not instances of List, but do implement the IEnumerable interface. They may implement ICollection, IList, etc, but you can play around with that.
I use Asp.Net MVC, Entity Framework. I have a form it looks like below.
Here, dropdownlist is filled from a table(types). Checkboxes is filled from another table(test). Tables are like below:
public class Types
{
public int TypesID{get;set;}
public string TestName { get; set; }
public string TestExplanation { get; set; }
public int TestTime { get; set; }
}
public class Tests
{
public int TestID{get;set;
public string Name { get; set; }
public string Code { get; set; }
}
public class Types_Tests
{
public int Types_TestsID{ get; set; }
public int TypesID { get; set; }
public int TestsID { get; set; }
public virtual Types Types { get; set; }
public virtual Tests Tests { get; set; }
}
Types_test table is relation table between Types and Tests. When I click Kaydet button, it shuld save type and checked tests. I made this operation using ViewBag, javascript and hdnvalue.I added checked checkboz values to a hdntext. I made saving process like below:
[HttpPost]
public ActionResult Index(string drpType, string hdntesttypes)
{
var TypeList = Types.GetAll();
ViewBag.TypesList = new SelectList(TypeList, "Id", "Name");
var testypeList = testTypes.GetAll();
ViewBag.TestTypesList = new SelectList(testypeList, "Id", "TestName");
GenericRepository<TestDisabledTypes> testDisabledRepository = new GenericRepository<TestDisabledTypes>(_context);
if (!string.IsNullOrEmpty(hdntesttypes))
{
string[] disabletypesArray = hdntesttypes.Split(',');
using (TransactionScope trns = new TransactionScope())
{
for (int i = 0; i < disabletypesArray.Length; i++)
{
Test_Types types = new Test_Types ();
types.TestTypesID = Convert.ToInt32(disabletypesArray[i]);
types.TypesID = Convert.ToInt32(drpType);
testDisabledRepository.Insert(types);
}
trns.Complete();
}
}
return View();
}
It wokrs. But I search better solution for this process. Can someone give me any idea?
Thanks.
If you don't need additional attributes for your entity class, you don't need create link table.
Just define the following class, and EF will generate the link table for you automatically.
public class Type
{
public int TypesID{get;set;}
public string TestName { get; set; }
public string TestExplanation { get; set; }
public int TestTime { get; set; }
public ICollection<Test> Tests { get; set; }
}
public class Test
{
public int TestID{get;set;
public string Name { get; set; }
public string Code { get; set; }
public ICollection<Type> Types {get;set;}
}
Well, in EntityFramework if you want to create a many to many relation object you need to create new object of "linking" entity. Unfortunately, it is not possible to add first object, add second object and say "Guys, you are in many to many relationships. Are you happy then?" :) You need to create relation object, set appropriate fields in it (I think these are ids of two objects itself) and add it to relation collection (entity) in your model. But before doing so you need to be sure that objects with data you are linking with are already exists in database. Otherwise you'll get an error
Also it's not necessary to create manually transaction because EF does it for you automatically each time you get/save your data
I'm using ASP.NET MVC4 EF CodeFirst.
Need help to write LINQ (to entities) code in Index action to get collection of Courses which are attended by selected student. The relationship is many to many with join table with payload.
//StudentController
//-----------------------
public ActionResult Index(int? id)
{
var viewModel = new StudentIndexViewModel();
viewModel.Students = db.Students;
if (id != null)
{
ViewBag.StudentId = id.Value;
// *************PROBLEM IN LINE DOWN. HOW TO MAKE COURSES COLLECTION?
viewModel.Courses = db.Courses
.Include(i => i.StudentsToCourses.Where(t => t.ObjStudent.FkStudentId == id.Value));
}
return View(viewModel);
}
The error I got is:
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
I have modeles (the third one is for join table with payload):
//MODEL CLASSES
//-------------
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public virtual ICollection<StudentToCourse> StudentsToCourses { get; set; }
}
public class Course
{
public int CourseId { get; set; }
public string Title { get; set; }
public virtual ICollection<StudentToCourse> StudentsToCourses { get; set; }
}
public class StudentToCourse
{
public int StudentToCourseId { get; set; }
public int FkStudentId { get; set; }
public int FkCourseId { get; set; }
public string Classroom { get; set; }
public virtual Student ObjStudent { get; set; }
public virtual Course ObjCourse { get; set; }
}
Then, here is modelview I need to pass to view
//VIEWMODEL CLASS
//---------------
public class StudentIndexViewModel
{
public IEnumerable<Student> Students { get; set; }
public IEnumerable<Course> Courses { get; set; }
public IEnumerable<StudentToCourse> StudentsToCourses { get; set; }
}
EF does not support conditional include's. You'll need to include all or nothing (ie no Whereinside the Include)
If you need to get the data for just certain relations, you can select it into an anonymous type, something like (the obviously untested);
var intermediary = (from course in db.Courses
from stc in course.StudentsToCourses
where stc.ObjStudent.FkStudentId == id.Value
select new {item, stc}).AsEnumerable();
Obviously, this will require some code changes, since it's no longer a straight forward Course with a StudentsToCourses collection.