MVC, c# .edmx file - Adding a new controller - asp.net-mvc

I am adding a new controller that makes use of a number of tables. I have added these tables to the .edmx file. For the add new controller dialog box, it ask for the Model Class. I do see the 3 tables I dropped into the .edmx but not sure which one to choose or if there is a way to choose a model that is a consolidated version of those 3 tables.

This is where a view model would come into play. First of all create a view model that contains properties for the 3 models you want to render on your view:
public class FakeViewModel
{
public Product Product { get; set; }
public Company Company { get; set; }
public User User { get; set; }
}
In your controller, create a new instance of the view model and populate it accordingly. EG:
public ActionResult FakeAction(int id)
{
var product = _repository.Get<Product>(id);
var company = _repository.Get<Company>();
var user = _repository.Get<user>();
var model = new FakeViewModel{
Product = product,
Company = company,
User = user
};
return View(model);
}
On your view, you will now have a strongly typed view for the FakeViewModel.

Related

Editing some properties of View Model in ASP.NET MVC

I'm using Entity Framework Database First approach. Let's say I have a model class called Product and that class has a NumberOfViews property. In the Edit page I pass an instance of the product class to the controller.
The problem is I can't add #Html.EditorFor(model => model.NumberOfViews) in the Edit page, because it's supposed that NumberOfViews is updated with every visit to the product page, and NOT by the website Admin.
And I can't add it as #Html.HiddenFor(model => model.NumberOfViews), because if the Admin Inspected the element, he can edit it manually.
Also If I try to programmatically set the value on the server-side (e.g., Product.NumberOfViews = db.Products.Find(Product.Id).NumberOfViews;), I get the following error:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
And if I don't add it to either the view or the controller, the value will be null, thus overriding any previous value.
So what should I do?
I have noticed a lot of people use the same model for their Entity Framework as they do for their MVC Controller. I generally discourage this practice. In my opinion, a database model is not the same as a view model.
Sometimes a view needs less information than what the database model is supplying. For example while modifying account password, view does not need first name, last name, or email address even though they may all reside in the same table.
Sometimes it needs information from more than one database table. For example if a user can store unlimited number of telephone numbers for their profile, then user information will be in user table and then contact information with be in contact table. However when modifying user profile, they may want to add/edit/delete one or more of their numbers, so the view needs all of the numbers along with first name, last name and email address.
This is what I would do in your case:
// This is your Entity Framework Model class
[Table("Product")]
public class Product
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ProductId { get; set; }
public string Name { get; set; }
public int NumberOfPageViews { get; set; }
}
// This is the model you will use in your Edit action.
public class EditProductViewModel
{
public int ProductId { get; set; }
public string Name { get; set; }
}
public class ProductController : Controller
{
IProductService service;
//...
[HttpGet]
public ActionResult Edit(int productId)
{
var product = service.GetProduct(productId);
var model = new EditProductViewModel()
{
ProductId = product.ProductId,
Name = product.Name
};
return View(model);
}
[HttpPost]
public ActionResult Edit(EditProductViewModel model)
{
if (ModelState.IsValid)
{
var product = service.GetProduct(model.ProductId);
product.Name = model.Name;
service.Update(product);
}
// ...
}
}

MVC Viewmodel cant access model with View

How can I access my viewmodel from my view? my code is as follows:-,
I have two models (using entity framework) which have a view model of:-
public class ViewModelStory
{
public IEnumerable<tbl_GCB_NewsItem> GCB_NewsItem { get; set; }
public IEnumerable<tbl_GCB_ItemComment> comemnts { get; set; }
}
My contoller populates the models by:-
ViewModelStory.GCB_NewsItem = (from i in db.tbl_GCB_NewsItem
where i.intItemIdentifier.ToString() == StoryId
select i).SingleOrDefault();
ViewModelStory.comemnts = (from i in db.tbl_GCB_ItemComment
where i.intItemIdentifier.ToString() == StoryId
select i).ToList<tbl_GCB_ItemComment>();
I return the model by
return PartialView("NewsStory", ViewModelStory);
then in my view I have the following declaration
#model ViewModelStory
#using GCBSMVC.Models
To access my model I have tried various from Linq to and directly querying the model, but nothing seems to work:-
Html.DisplayFor(m =>m.GCB_NewsItem. ....
ViewModelStory.GCB_NewsItem.strItemCategory
Html.Raw(System.Web.HttpUtility.HtmlDecode(ViewModelStory.GCB_NewsItem.strItemHeadline))
You are passing the type of you model class instead of the actual class. Try this:
var model = new ViewModelStory();
model.GCB_NewsItem = (from i in db.tbl_GCB_NewsItem
where i.intItemIdentifier.ToString() == StoryId
select i).SingleOrDefault();
model.comemnts = (from i in db.tbl_GCB_ItemComment
where i.intItemIdentifier.ToString() == StoryId
select i).ToList<tbl_GCB_ItemComment>();
return PartialView("NewsStory", model);

Simple approach to CRUD intersection table in MVC ASP.NET and EF?

I am using C#, MVC3, EF5, SQL Server 2008 R2.
I have an intersection table ie
Lecturer -< LecturerCourse >- Course
The list of Lecturers are populated.
When I add a course, it would be neat to have a list of Lecturers that I could select from, that teach the course in question. When I save the new Course record, this multiselect also should save its data back to the "LecturerCourse" table via Model Binding.
I am using EF5.
Can you recommended a simple and standard approach to solving CRUD for a join, ie "LecturerCourse", table? I have looked online, but some of the approaches seem very complicated.
Many thanks.
Alright, it's going to be a long one. To allow this to happen in "one page" (through POST, or you could use Ajax, technically), you need a combination of a Get and Post version of the method and to construct your view model correctly. Below are the classes that I will use for demonstration purposes:
public class NewCourse
{
[Required]
public string Name { get; set; }
// And your other properties
public int[] LecturerIds { get; set; }
}
public class ViewLecturer
{
public int Id { get; set; }
public int Name { get; set; }
}
public class NewCourseViewModel
{
public NewCourse Course { get; set; }
public IEnumerable<ViewLecturer> Lecturers { get; set; }
}
NewCourseViewModel will be the model for the View (see below). ViewLecturer will give you a lighter mapping between your available Lecturer and the information required to Add to them.
As for the Controller:
public class CourseController : Controller, IDisposable
{
private Lazy<YourContext> lazyContext =
new Lazy<YourContext>(() => new YourContext());
private YourContext Context
{
get { return lazyContext.Value; }
}
public ActionResult New()
{
var model = new NewCourseViewModel {
Course = new NewCourse(),
Lecturers = Context.Lecturers
.Select(l => new ViewLecturer { Id = l.Id, Name = l.Name })
};
return View(model);
}
[HttpPost]
public ActionResult New(NewCourse course)
{
if(ModelState.IsValid)
{
var lecturers = course.Lecturers
.Select(l => new Lecturer { Id = l.Id })
.ToList();
foreach(var lecturer in lecturers)
Context.Lecturers.Attach(lecturer);
var newCourse = new Course {
Name = course.Name,
// ... and the rest of the mapping
Lecturer = lecturers
};
context.Courses.Add(newCourse);
context.SaveChanges();
// Could have to handle DbUpdateException if you want
return RedirectToAction(...);
}
return View(new NewCourseViewModel {
Course = course,
Lecturers = Context.Lecturers
.Select(l => new ViewLecturer { Id = l.Id, Name = l.Name })
});
}
public void Dispose()
{
if(lazyContext.IsValueCreated)
lazyContext.Value.Dispose();
}
}
Your first New method will give you the entry point for your Course creation page. The rest of the validation and actual adding will be done through the [HttpPost]overload. As for your View (that should be in the ~/Views/Course/New.cshtml):
#model NewCourseViewModel
// ... Then when you are ready to begin the form
#using(Html.BeginForm("New", "Course", FormMethod.Post))
{
// Your List of Lecturers
#Html.ListBoxFor(m => m.Course.LecturerIds,
new MultiSelectList(
Model.Lecturers,
"Id",
"Name",
m.Course.LecturerIds ?? new int[0]
))
// Your Other Model binding
}
When the submit button will be pressed, the action matched will be the New(NewCourse course). The names are important because of the way the HtmlHelpers generate their Ids. Because we are only included one property of the whole view model, it will match the parameter name course based on the view model's Course property. You will get a list of Ids for the Lecturers which you will be able to use to attach to the DbContext and add directly to the new Course model (Entity Framework will do the rest). In cases where there was a problem, we can get back the list of lecturers and re-use the same NewCourse in the view model.
Now this is example is very basic but it should give you a good starting point as to how you can structure your view model.

View with Many to many relationship

I came across the following situation:
I have 2 tables:
Eventos and Convidados
I had to create a third table to associate multiple
id_evento and id_convidado
I've created a controller called EventoConvidado and need to display on the screen all Convidados.
How I do to pass the model to the View?
I found only one question in your description - how to pass a model to a view.
You create a view model called EventosConvidadosViewModel like this:
public class EventosConvidadosViewModel
{
public Eventos Eventos { get; set; }
public Convidados Convidados { get; set; }
}
In the controller you do something like this:
public ActionResult Index()
{
var viewModel = new EventosCandidatosViewModel();
// should you need to fill in the parameters for the view model you do it here
return View(viewModel);
}
In the view your first line should be
#model EventosCandidatosViewModel;
You use this model inside the view in the following manner: #Model. You access its properties like this: #Model.Eventos or #Model.Convidados.
Hope this helps you.

pass an anonymous type to my ASP.NET MVC view

I have a problem, I have the next controller
namespace RolesMVC3.Areas.Administrador.Controllers
{
[Authorize(Roles = "Adminr")]
public class HomeController : Controller
{
private BASEDATOSCJ_2Entities db = new BASEDATOSCJ_2Entities();
public ActionResult Index()
{
string username = User.Identity.Name;
MembershipUser user = Membership.GetUser(username);
Guid key = (Guid)Membership.GetUser().ProviderUserKey;
var Universities = (from u in db.UNIVERSITy
join s in db.CAMPUS_UNIVERSITy on u.IdUniversity equals s.IdUniversity
join c in db.CIUDAD_CAMPUS on s.IdCiudadSede equals c.IdCiudadSede
join co in db.OFFICE on s.Idoffice equals co.Idoffice
join uxc in db.USERxOFFICE on co.Idoffice equals uxc.Idoffice
where uxc.UserId == key
select new { u.Name, namecity = c.Nombre, s.Idoffice}).ToList();
return View(Universities);
}
With this controller I just want send to View u.Name, and s.Idoffice. How I do? (in fact do not know if this controllet is fine), I want to send fields belong to different tables. I want to send the query as a list and present at the View, ViewBag go with it?, How do I pass these data to the view and display with a foreach?.
I use razor
If you change the following line:
select new { u.Name, namecity = c.Nombre, s.Idoffice}
To
select new { Name = u.Name, Idoffice = s.Idoffice }
This only selects the two fields into a list. In your view you can do the following:
#model List<dynamic>
#foreach(dynamic d in Model) {
<p>#d.Name</p>
<p>#d.Idoffice</p>
}
Edit:
You might want to define a ViewModel to contain your data.
public class MyViewModel {
string Name {get;set;}
string Idoffice {get;set;}
}
Now you can change your select statement as follows:
select new MyViewModel { Name = u.Name, Idoffice = s.Idoffice }
And update your Razor file as such:
#model List<MyViewModel>
#foreach(MyViewModel d in Model) {
<p>#d.Name</p>
<p>#d.Idoffice</p>
}
I would use a view model. I have learnt not to expose my domain objects to the view, I rather map my domain object to the view model and return this view model to the view.
Separate you data access logic from your view logic. You can put that whole statement into a repository class and then you just call this method from the controller.
Here is a partial view model, you might have more properties if you need more data to be displayed:
public class UniversityViewModel
{
IEnumerable<University> Universities { get; set; }
}
University class:
public class University
{
public string Name { get; set; }
public string Idoffice { get; set; }
}
In my action method of my controller it would look something like this:
public ActionResult Index(int id)
{
UniversityViewModel viewModel = new UniversityViewModel
{
Universities = universityRepository.GetAll()
};
return View(viewModel);
}
And in my view I would have the following:
<table>
#foreach(University university in Model.Universities)
{
<tr>
<td>Name:</td>
<td>university.Name</td>
</tr>
}
</table>
This is just a basic display of data in the view, you can use 3rd party components to display your data with some features.

Resources