How to make one-to-many relationship with asp identity users - asp.net-mvc

Im using the default Web Application with MVC + Identity for managing users, and im trying to make every registered user to make his movie list and to be able to see only his list when logs in.
So, for my example i have made a movie class
public class Movie
{
public int MovieId { get; set; }
public string MovieName { get; set; }
public string Year { get; set; }
public string Genre { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
and in ApplicationUser i have put
public virtual ICollection<Movie> Movies { get; set; }
to have a list of movies.
I also made a Entity FrameWork MovieController, used Movie as model and ApplicationDbContext as context.
So i have problems querying the db in order to get each user to view only his movie list, with the default scaffolding i get this in index action of MoviesController
public ActionResult Index()
{
var movies = db.Movies.ToList();
return View(movies);
}
If anyone has experience with my problem please help, any input is welcomed and much appreciated.

You need to add one more property in your movie class of ApplicationUserID for creating proper relationship between them like this:
public class Movie
{
public int MovieId { get; set; }
public string MovieName { get; set; }
public string Year { get; set; }
public string Genre { get; set; }
public string ApplicationUserID { get;set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
Now you can get all movies for a user like this:
public ActionResult Index()
{
ApplicationDbContext context = new ApplicationDbContext();
string userid = User.Identity.GetUserId();
IEnumerable<Movie> movies = new List<Movie>();
if (!string.IsNullOrEmpty(userid))
{
movies = context.Movies.Where(x => x.ApplicationUserID == userid);
}
return View(movies);
}

First you should change your link to applicationuser (from Movie) to be a collection (many to many).
public virtual ICollection<Movie> Movies { get; set; }
If you want to fetch a list of movies for the logged in user you can fetch the user and movie list like this:
var user = UserManager.FindById(User.Identity.GetUserId());
Debug.WriteLine(user.Email);
var movies = user.Movies.ToList();
foreach (var movie in movies)
{
Debug.WriteLine(movie.MovieName);
}
Instead of writing to the debug window you could return a view with movies like you have done in your own code.
-
I would also suggest that you make use of viewmodels for sending data to/from your views. The way you are doing it now could potentially send the entire database to your view (depending on your query ofc). You will also get a more granulated control of what you display to the user. (you could read this: what-is-viewmodel-in-mvc to get you started)

Related

Multiple tables update MVC .net

I am new to MVC and this is my function. There are three tables (Order, OrderNotes, Notes), ID is their primary key. One Order can have many Notes, the table OrderNotes has foreign key OrderID(from Booking table) and NotesID(from Notes table). I want to have a Order Edit page to display individual Order (FirstName, LastName), also display a list of its Notes. Here is my DB structure:
Booking table:
{ID,
FirstName,
LastName
}
BookingNotes table:
{ID,
BookingID,
NotesID
}
Notes table:
{ID,
NoteName,
StatusID
}
So how can I implement the list of Notes since it's from multiple tables? It will be able to Create New Note, Delete existing Note in the list row record, not Edit. Linq used in DB query. Thanks.
It would be a better idea to have only 2 tables:
public class Book
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Navigational properties
public virtual List<Note> Notes { get; set; }
}
public class Note
{
public int ID { get; set; }
public int BookID { get; set; }
public string NoteName { get; set; }
public int StatusID { get; set; }
// Navigational properties
public virtual Book Book { get; set; }
public virtual Status Status { get; set; }
}
A third table is useful when you want to reuse the same Note for a different booking. However i think this is not the case.
So to retrieve data for your context make sure you have the DbSet<Book>
public class ApplicationDbContext : DbContext
{
public virtual DbSet<Book> Bookings { get; set; }
}
In your controller (or better in a repository class):
var BookingID = 10; // this is parameter passed to the function
var myBooking = this.dbContext.Bookings
.Include(p => p.Notes)
.ThenInclude(p => p.Status)
.FirstOrDefault(p => p.ID == BookingID);
Map the retrieved booking to a ViewModel, pass it to the View and you're good to go.

How to create different data with each different user?

Im using asp.net entity framework and asp.net identity, and what im trying to do is to register with some account and to make some data with user#1(agentmi6) like:
and then log in with user#2(john) and make some data with this user:
so my main problem is how to make users view only their created data.
In my movie model i added a relation with application user
public class Movie
{
[Key]
public int MovieId { get; set; }
public string Name { get; set; }
public string Year { get; set; }
public string Genre{ get; set; }
public string ApplicationUserID { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
}
then in MoviesController added this query to get all movies created by the current registered user:
public ActionResult Index()
{
var currentUser = User.Identity.GetUserId();
var movies = db.Movies.Where(x => x.ApplicationUserID == currentUser);
return View(movies);
}
and in the Create action of the controller when i create a movie i add the current user to that movie
public ActionResult Create(Movie movie)
{
if (ModelState.IsValid)
{
movie.ApplicationUserID = User.Identity.GetUserId();
db.Movies.Add(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
in all Views of MoviesController i removed the application user html since i dont want to show in index and when creating movies.
and in the end i got what i was looking for.
Login with user a#a.com and made a movie which is only visible to him,
and second user v#v.com that can see only his movie.

MVC parameter not binding to controller action (KENDO UI)

Hope someone can help - this has been bugging me for around 2 hours - its probably something simple :)
Kendo UI Grid sends a request to my controller
http://localhost:1418/user/update?UserID=1&UserName=Admin&RoleName=Admin&Email=c.j.hannon%40gmail.com&Active=true&Company%5BCompanyID%5D=1&Company%5BCompanyName%5D=asd
However, the controller class 'Company' isnt bound by the binder? Can any one help my view model and controller action signature are below:
[HttpGet]
public JsonResult Update(UserViewModel model)
{
svcUser.UpdateUser(new UpdateUserRequest() {
UserID=model.UserID,
RoleID = model.RoleName,
Email = model.Email,
Active = model.Active.GetValueOrDefault(false),
UserName = model.UserName
});
return Json("", JsonRequestBehavior.AllowGet);
}
public class UserViewModel
{
public int UserID { get; set; }
public string UserName { get; set; }
public string RoleName { get; set; }
public string Email { get; set; }
public bool? Active { get; set; }
public CompanyViewModel Company { get; set; }
}
Cheers
Craig
A few things. Your immediate problem is that Company is mapped to a complex object not a primitive type. Kendo Grid just does not do this (as of this writing). Just guessing, but you probably want to setup a foreign key binding on the Grid and just pass back the Id of the company from a listbox. This is not as bad as you think and it will immediatly fix your problem and look nice too.
Maybe personal taste but seems to be a convention. Use the suffix ViewModel for the model that is bound to your View and just the suffix Model for your business objects. So a Kendo Grid is always populated with a Model.
Ex.:
public class UserModel
{
public int UserID { get; set; }
public string UserName { get; set; }
public string RoleName { get; set; }
public string Email { get; set; }
public bool? Active { get; set; }
public int CompanyID { get; set; }
}
public class CompanyModel
{
public int ID { get; set; }
public string Name { get; set; }
}
public class UserViewModel
{
public UserModel UserModel { get; set; }
public IList<CompanyModel> Companies { get; set; }
}
public ActionResult UserEdit(string id)
{
var model = new UserViewModel();
model.UserModel = load...
model.Companies = load list...
return View(model);
}
#model UserViewModel
...
column.ForeignKey(fk => fk.CompanyId, Model.Companies, "ID", "Name")
(Razor Notation)
BUT! This is just an example, you are better off Ajax loading the Grid with the IList becuase I assume you have many Users in the Grid at once, though you could server bind off the ViewModel with a List too. But the list of Companies is probably the same every time, so map it to the View just liek this rather than Ajax load it every time you do a row edit. (not always true)

ASP.NET MVC: Displaying multiple models in one view (one-to-many relationship)

I'm trying to put together (what I thought was) a simple ASP.NET web application using MVCScaffolding and ASP.NET. There is a basic hieararchy of data tables in SQL: dbo.Albums, dbo.Tracks.
The model is easy. For albums:
public class Albums {
public int ID { get; set; }
public string Artist { get; set; }
public string AlbumTitle { get; set; }
public string Notes { get; set; }
}
public class Tracks {
public int ID { get; set; }
public int AlbumID { get; set; }
public string TrackTitle { get; set; }
public string Notes { get; set; }
}
The basic CRUD views are built and working fine. However, I'm trying to build a view that displays the Album model data followed by a table with one row for each track record for a given AlbumId. Essentially, this is the Details view followed by the Index view from the MVCScaffolding template, but it uses two Models and has one parameter (the ID from Albums table).
I tried to add the models together to access the data from there, but I can't figure out how to iterate over a list (the index view uses #model IEnumerable<Music.Models.Tracks>). This is the combined model:
public class AlbumsExtended
{
public Albums Albums { get; set; }
public Tracks Tracks { get; set; }
}
And I am trying to access it in AlbumsExt.cshtml with #model Music.Models.AlbumsExtended. The controller looks like this:
public ViewResult AlbumExt(int id)
{
return View(tracksRepository.All.Where(tracks => tracks.AlbumId == id));
}
But obviously that isn't correct.
Given your structure of Albums and Tracks, it would probably be preferable to have a direct 1 to many relationship between Albums and Tracks so that 1 album can have many tracks. Regardless of how many albums a track may appear on, your models could look like:
public class Albums {
public int ID { get; set; }
public string Artist { get; set; }
public string AlbumTitle { get; set; }
public string Notes { get; set; }
public IQueryable<Track> Tracks { get; set; }
}
public class Track {
public int ID { get; set; }
public int AlbumID { get; set; } // This may be unnecessary
public string TrackTitle { get; set; }
public string Notes { get; set; }
}
This would allow your data layer to populate all of the tracks that belong to a specific Album, but if you don't need to know the tracks it can just remain null. But your data layer just needs to fetch the album and then populate the Tracks property with an IQueryable object.
public ViewResult AlbumExt(int id)
{
Album album = albumRepository.All.Where(a => a.ID == id);
album.Tracks = tracksRepository.All.Where(t => t.AlbumId == id);
return View(album);
}
This would give you a single model, but all of the related tracks would still be accessible through the Model.Tracks property in the view:
#model MyNameSpace.Album
#{
foreach (var track in Model.Tracks)
{
<text>
<h1>#track.TrackTitle</h1><br />
</text>
}
}

get Membership user object from another model

i want something like this :
public class Order
{
public Guid OrderID { get; set; }
public Guid UserId { get; set; }
public DateTime OrderDate { get; set; }
public decimal Amount { get; set; }
public virtual ICollection<OrderDetail> orderDetailByOrderID { get; set; }
public virtual MembershipUser userByOrderID { get; }
}
so from above code i want membership user to be access from Order object ....
however i tried it but its not working.
so please suggest some solution if you have come across this type situation
It sounds like you might be using Entity Framework Code First. If this is the case you'd probably want:
public virtual aspnet_Membership userByOrderID { get; set; }
instead of
public virtual MembershipUser userByOrderID { get; }
That would grab the aspnet_Membership entity that is tied to the UserId foreign key. The aspnet_Membership class is not quite the same as the MembershipUser entity, but they have many of the same properties.
If that won't work, you can always use your Order model as is, and generate a ViewModel that has the MembershipUser object.
public class OrderViewModel
{
public Order Order { get; set; }
public MembershipUser User { get; set; }
}
and create the ViewModel like this before passing it into a view
Order order = EntityDataContext.Orders.First();
var model = new OrderViewModel { Order = order, User = Membership.GetUser(order.UserId) }

Resources