Using LINQ with C# MVC - c#

I am stuck on a problem implementing LINQ properly on my model. Right now I have it so that when the user clicks on the "list tracks" view they will receive a listing of every song in the DB. What i want to do, is add another link at the top such as "pop tracks" and have it when the user clicks on it, it will sort all the songs by their GenreId (pop) which is 9. I am unsure how to accomplish this as i don't understand how you would return multiple views from 1 index() method (if that's even how i would do it?). Any help is appreciated.
I am now receiving this error:
xception Details: AutoMapper.AutoMapperMappingException: Missing type
map configuration or unsupported mapping.
Mapping types: Genre -> TrackBase Assignment_3.Models.Genre ->
Assignment_3.Controllers.TrackBase
Source Error:
Line 74: { Line 75: var AllPop = ds.Genres.Where(p
=> p.GenreId == 9); Line 76: return mapper.Map>(AllPop); Line 77: } Line
78:
Manager.cs:
public IEnumerable<TrackBase> TrackGetAll()
{
return mapper.Map<IEnumerable<Track>, IEnumerable<TrackBase>>(ds.Tracks);
}
public IEnumerable<TrackBase> TrackGetAllPop()
{
var AllPop = ds.Genres.Where(p => p.GenreId == 9);
return mapper.Map<IEnumerable<TrackBase>>(AllPop);
}
TrackController.cs:
public ActionResult Index(int? genreid)
{
if (genreid.HasValue && genreid.Value == 9)
{
return View(m.TrackGetAllPop());
}
return View(m.TrackGetAll());
}
AutoMapperConfig.cs:
cfg.CreateMap<Models.Track, Controllers.TrackBase>();
cfg.CreateMap<Controllers.TrackBase, Controllers.TracksController>();

You need to pass the genre id to Index action method and filter the songs accordingly. Change your controller to this
public ActionResult Index(int? genreid)
{
if (genreid.HasValue && genreid.Value == 9)
{
// return all pop songs to the view
return View(m.TrackGetAllPop());
}
// return all songs to the view
return View(m.TrackGetAll());
}
then in your index
#Html.ActionLink("All Tracks", "Index") |
#Html.ActionLink("Pop Tracks", "Index", new { genreid = 9})
You also have a problem with TrackGetAllPop method
public IEnumerable<TrackBase> TrackGetAllPop()
{
var AllPop = ds.Genres.Where(p => p.GenreId == 9);
return mapper.Map<IEnumerable<TrackBase>>(AllPop);
}
The above method returns IEnumerable<TrackBase> but you're querying from ds.Genres instead of ds.Tracks, so that's why you got the error. Assuming Track table has GenreId as the foreign key to the Genre table, TrackGetAllPop method should be like below
public IEnumerable<TrackBase> TrackGetAllPop()
{
var AllPop = ds.Tracks.Where(p => p.GenreId == 9);
return mapper.Map<IEnumerable<TrackBase>>(AllPop);
}
More General Solution
The above will work for this particular case, however you can make it more general for other genres too. Add this method in Manager.cs
public IEnumerable<TrackBase> TrackGetByGenre(int genreId)
{
var result = ds.Tracks.Where(p => p.GenreId == genreId);
return mapper.Map<IEnumerable<TrackBase>>(result);
}
and change your controller to below
public ActionResult Index(int? genreid)
{
if (genreid.HasValue)
{
// return songs based on the passed genreid to the view
return View(m.TrackGetByGenre(genreid.Value));
}
// return all songs to the view
return View(m.TrackGetAll());
}

Related

RedirectToAction to multiple HttpPost Action

I created a button that directs to another page with 3 tabs.
These 3 subtabs has different input text and only using 1 Action [HttpGet].
These are my cases.
I want to save only first tab data, the 2 tabs value will be null
I want to save only second data, the 1st tab and 3rd tab will be null
I want to save all the text input that I've typed under 1st tab, 2nd tab, and 3rd tab.
Here is my code:
[HttpGet]
public ActionResult Create_Data(int productId)
{
var model = BigViewModel();
///rest of code
return View(model)
}
[HttpPost]
public ActionResult Create_Data(BigViewModel model, int productId)
{
int experimentForOverloading = 0;
string experimentAgain = ""
// validates if first tab and doesn't have data inputted, will redirect to Create_SecondTab. Below is just for testing
if (model.FirstTabName == null && model.ThirdTabDirectory == null)
{
// this is where I want to go to route the new Action. But I don't know what to do..
return RedirectToAction("CreateData", new
{
model = BigViewModel,
Id = productId,
experimentForOverloading
}
}
else if (model.SecondTabSalary == null && model.ThirdTabDirectory == null)
{
return RedirectToAction("CreateData", new
{
model = BigViewModel,
Id = productid
experimentAgain
}
}
else
{
return RandomView(); //Testing purposes
}
}
// This is the second case, save only when first tab is empty
[HttpPost]
public ActionResult CreateData(BigViewModel, int bigId, int experimentForOverloading)
{
if(ModelState.IsValid)
{
//.. code here
_context.SaveChanges()
}
else
{
return RandomView(); //Testing purpose
}
}
// This is the first case, save only when second and third tab is empty
[HttpPost]
public ActionResult CreateData(BigViewModel, int bigId, string experimentAgain)
{
if(ModelState.IsValid)
{
//.. code here
_context.SaveChanges()
}
else
{
return RandomView(); //Testing purpose
}
}

Show buttons on a partial view based on some query

I am showing search results same as searching groups on facebook
enter image description here
I have a relationship Table named CommunityUser in Database having attributes CommunityID and UserID.
Using Partial View I want to show if User not already joined that Community/Group that it will show Join Button else if user already joined that community it will show Leave button.
I have written IsMember() function in my controller that takes two parameters, CommunityID and UserID. This will return true if that Community ID exist against that user ID.
public bool IsMember(string UserID, int CommunityID) {
var Membership = db.Users.Include(x => x.CommunityUsers).Where(s => s.Id.Equals(UserID)).Count();
if(Membership>0)
return true;
else
return false;
}
Now what I actually need is, I want to call this function in an IF condition on my view class. It is not allowing me to call this function on my view Class.
#if (){
<button>#Html.ActionLink("Leave", "LeaveCommunity", new { id = ViewBag.ComID })</button>
}
else
{
<button>#Html.ActionLink("Join", "joinCommunity", new { id = ViewBag.ComID })</button>
}
In your controller you should have a method which will return this view. So in this method you call this function
public ActionResult Index(string UserID, int CommunityID)
{
var hasMembership = IsMember(serID, CommunityID);
return View(hasMembership);
}
In the View it self then you just grab this variable hasMembership you just passed from #model.
#if (Model){
<button>#Html.ActionLink("Leave", "LeaveCommunity", new { id = ViewBag.ComID })</button>
}
else
{
<button>#Html.ActionLink("Join", "joinCommunity", new { id = ViewBag.ComID })</button>
}
Note: it might be wise to create some DTO class for passing data to a view, because you might need to pass multiple value to a view at some point. Plus the whole condition would be more readable
public SomeDTO {
public bool IsMember {get;set}
public List<Community> Communities {get;set;}
}
public ActionResult Index(string UserID, int CommunityID)
{
var hasMembership = IsMember(serID, CommunityID);
var listOfCommunities = _repo.GetComunities();
var dto = new SomeDTO
{
IsMember = hasMembership,
Communities = listOfCommunities
}
return View(dto);
}
#if (Model.IsMember){
// do or do not something
}

MVC data passing in view

I am making my MVC application. I open my view with predefined parameters like this:
return RedirectToAction("PickGroupForHomework", "Account", new {subject_id = id, qty=model.qty });
And this works fine, the data subject_id and qty are passed correctly. However, my view PickGroupForHomework contains a form to fill, which is then validated. If the input is not valid, the window simply should reload with the data subject_id and qty as defined in previous view. I do this in such way:
public ActionResult PickGroupForHomework(PickGroupForHomeworkViewModel model)
{
ClassDeclarationsDBEntities2 entities = new ClassDeclarationsDBEntities2();
model.groups = entities.Groups.ToList();
model.users = entities.Users.ToList();
int id = model.subject_id;
var subj = entities.Subjects
.Where(b => b.class_id == model.subject_id)
.FirstOrDefault();
if (subj != null)
{
model.subject_name = subj.name;
}
if (ModelState.IsValid)
{
}
else
{
return View(model);
}
return View(model);
}
But the resulting URL does not contain the data I need, but just a plain view. How do I do it right?
In order for you wep app to work, you will need two actions, one to set your model up for the View and another to actually do the work to post and save your data:
public ActionResult PickGroupForHomework(int subject_id, int qty)
{
//Initialize your model here. Below is just an example.
ClassDeclarationsDBEntities2 entities = new ClassDeclarationsDBEntities2();
PickGroupForHomeworkViewModel model = new PickGroupForHomeworkViewModel();
model.groups = entities.Groups.ToList();
model.users = entities.Users.ToList();
model.subject_id = subject_id;
model.qty = qty;
return View("PickGroupForHomework", model);
}
[HttpPost]
public ActionResult PickGroupForHomework(PickGroupForHomeworkViewModel model)
{
ClassDeclarationsDBEntities2 entities = new ClassDeclarationsDBEntities2();
int id = model.subject_id;
var subj = entities.Subjects
.Where(b => b.class_id == model.subject_id)
.FirstOrDefault();
if (subj != null)
{
model.subject_name = subj.name;
}
if (ModelState.IsValid)
{
//Save to database
[code goes here]
//return to a View to show your results
return View("[Your view to see the results]")
}
//Model Validation did not pass
//or exception occurred go back to View
return View(model);
}

How to make Delete and Edit methods in MVC without DB

I am building a simple MVC CRUD without using a database, but just making methods in a Repository model class.
To make it easier to understand i have 2 model classes. MyNote in which i have some properties and NoteRepository in which i have a list with the properties.
Then I've made a NoteController and i have already made Get and Create methods, but i can't seem to figure out what to write to make an Edit and Delete method? Hope you guys can help.
Here you will see some of the code from my project:
[HttpPost]
public ActionResult Create(MyNote mn)
{
try
{
note.Create(mn);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
this is the create from the Controller.
public static List<MyNote> notes = new List<MyNote>();
public NoteRepository()
{
notes.Add(new MyNote() { ID = 1, Titel = "Morgenmad", OprettelsesDato = DateTime.Now, Note = "Spis morgenmad i dag" });
notes.Add(new MyNote() { ID = 2, Titel = "Frokost", OprettelsesDato = DateTime.Now, Note = "Spis frokost i dag" });
notes.Add(new MyNote() { ID = 3, Titel = "Aftensmad", OprettelsesDato = DateTime.Now, Note = "Spis aftensmad i dag" });
}
public void Create(MyNote mn)
{
notes.Add(mn);
}
here is the repository class with the list and the method for the create method.
and please, ask if i have missed something! Thank you :-)
It looks like you're using a List for your in-memory repository. For delete, you can implement something like this:
public bool Delete (MyNote noteToDelete) {
return notes.Remove(noteToDelete);
}
Edit: However, in this case, the list will check for reference equality. Since you have an ID, which I will assume is unique, you can instead do this:
public bool Delete(MyNote noteToDelete) {
var matchingNote = notes.FirstOrDefault(n => n.ID == noteToDelete.ID);
return notes.Remove(matchingNote);
}
You could also implement IEquatable on your MyNote class to change how your notes are compared with each other, and return a valid match when the IDs are the same.
For the IEquatable example, you would want to change the class definition for MyNote to look like:
public class MyNote : IEquatable<MyNote>
and add in the following code to the MyNote class:
public override bool Equals(object obj) {
if (obj == null) return false;
Part objAsNote = obj as MyNote;
if (objAsNote == null) return false;
else return Equals(objAsNote);
}
public bool Equals(MyNote otherNote) {
if(otherNote == null) return false;
return (this.ID.Equals(otherNote.ID));
}
public override int GetHashCode(){
return this.ID;
}
You can do something like this:
public ActionResult Edit(MyNote noteToEdit)
{
var oldNote = notes.FirstOrDefault(n => n.Id == noteToEdit.Id);
if(oldNote == null)
return View(); //With some error message;
oldNote.Title = noteToEdit.Title;
oldNote.OprettelsesDato = DateTime.Now;
oldNote.Note = noteToEdit.Note;
return RedirectToAction("Index", "Note");
}
public ActionResult Delete(int id)
{
var noteToRemove = notes.FirstOrDefault(x => x.Id == id);
if(noteToRemove == null)
return View(); //With some error message;
notes.Remove(noteToRemove);
return RedirectToAction("Index", "Note");
}
When you are editing your note, i recommend you to use AutoMapper to make your code more easy to maintain.

How to work with specific parameter of a Controller

The goal
Treat an offer as a category in controller.
The problem
I have a controller whose name is ProductsController. Inside it, I have an action called Category. When this method is requested, it responds with a view of products list that corresponds to the category passed as parameter. Follow the code:
[HttpGet]
public ActionResult Category(string categoryName = null)
{
if (Regex.Match(categoryName, #"\d+").Success)
{
int categoryId = Convert.ToInt32(Regex.Match(categoryName, #"\d+").Value);
string sluggedCategoryName = CommodityHelpers.UppercaseFirst(CommodityHelpers.GenerateSlug(Categories.GetDetails((sbyte)categoryId).Category_Name));
if (String.Format("{0}-{1}", categoryId, sluggedCategoryName) == categoryName)
{
ViewBag.Title = Categories.GetDetails((sbyte)categoryId).Category_Name;
ViewBag.CategoryProductsQuantity = Categories.GetDetails((sbyte)categoryId).Category_Products_Quantity;
ViewBag.CurrentCategory = sluggedCategoryName;
return View(Products.BuildListForHome(categoryId, null));
}
else
{
return View("404");
}
}
else
{
return View("404");
}
}
But I want to return other a specific view when "Offers" is passed as parameter.
How can I do this?
if (categoryName == "Offers")
return View("SomeView", Products.BuildListForHome(categoryId, null));
You can specify what view to return as a parameter like so:
return View("Offers", data);
Put an "if" "then" in the beginning of the method checking for Offers, and return your offers View if the conditions meet.

Categories

Resources