My Action
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
using (var ctx = new _dbContext())
{
return View(ctx.UserProfiles.OrderBy(x => x.UserId).ToList());
}
}
I want to display roles with UserId and UserName how can i do that??
Update:
View Model
public class AccountIndexViewModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Roles { get; set; }
}
View
#using GoldCalculator.Models
#model IEnumerable<AccountIndexViewModel>
#foreach (var user in Model)
{
<tr>
<td>#user.UserId</td>
<td>#user.UserName</td>
<td>#user.Roles</td>
<td> #Html.ActionLink("X", "Delete", new { id = #user.UserName }, new { #class = "deletebtn"})</td>
</tr>
}
The output is System.String[]
Assuming you have enabled roles in your application and that you have already created some roles:
using WebMatrix.WebData;
///blah blah blah...
///inside some action:
var roles = (SimpleRoleProvider)Roles.Provider;
var allRoles = roles.GetAllRoles();
Getting role for specific user:
var userRoles = roles.GetRolesForUser("admin#user.com");
Answering you new question, try this:
var model = ctx.UserProfiles.OrderBy(x => x.UserId);
var newModel = from ab in model
select new
{
UserName = ab.UserName,
UserId = ab.UserId,
Role = roles.GetRolesForUser(ab.UserName)
};
You are assigning value to variable that already has been declared and apparently data types don't match.
Related
var listdata = db.UserDetails.Select(m => new SelectListItem
{
Value = m.userid.ToString(),
Text = string.Format("{0}{1}{2}{3}",m.bankname,m.userid,m.gender,m.name)
});
Here UserDetails is the table that is present in the database and this is the way i am trying to display every entry of the table.
Controller
[HttpGet]
public ActionResult getAll()
{
var listdata = db.UserDetails.Select(m => new SelectListItem
{
Value = m.userid.ToString(),
Text = string.Format("{0}{1}{2}{3}",m.bankname,m.userid,m.gender,m.name)
});
return View("getAll", listdata);
}
View
#model UserApp.Models.UserDetails
#{
ViewBag.Title = "getAll";
}
<h2>getAll</h2>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
<td>
#Html.DisplayFor(modelItem => item.gender)
</td>
</tr>
}
Model
namespace UserApp.Models
{
public class UserModel : IEnumerable<UserModel>
{
public int userid {get; set;}
public string name{get; set;}
public IList<SelectListItem> bankname { get; set; }
public string gender{get; set;}
}
}
How do i get the elements and display them properly on the view?
I can't seem to get a proper solution.
Stuck on this thing for hours.
P.s: new to it, any help will be appreciated.
First, add ToList() for your listdata to make it list, currently it is still IQueryable , second your view accepts model, you are passing list of model, I guess you want that to be list not model, something like this
#model List<UserApp.Models.UserDetails>
Third, you are selecting SelectListItem but you are using UserApp.Models.UserDetails, I think you should be doing something like this
var listdata = db.UserDetails.ToList().Select(x => new UserApp.Models.UserDetails {
userid = x.userid, (repeat the same for all)
}).ToList();
because looking at your code you don't need selectListItem, you need UserApp.Models.UserDetails.
That should fix all your problems, I hope I didn't miss any.
My approach may not be the best approach but it seems to work for me.
I usually have my model for the item :
model :
namespace UserApp.Models
{
public class UserModel
{
public int userid {get; set;}
public string name{get; set;}
public IList<SelectListItem> bankname { get; set; }
public string gender{get; set;}
}
}
Then I have in my database class ( a class that calls the database and populates the queries etc: Call it CodeDB() for this example)
DB getter :
public List<UserModel> getUsers(){
{
List<UserModel> myUsers = new List<userModel>();
// however you are accessing your db do it here
string sql = "select * ...";
//access DB
//open connection
//run query command usually for me it is rdr = cmd.ExecuteReader();
while(rdr.Read()){
UserModel retrievedUser = new UserModel();
retrievedUser.userid = (int)rdr[0];
retrievedUser.name = rdr[1].ToString();
... add the other fields
myUsers.Add(retrievedUser);
}
//close db connection
return myUsers
}
In my Controller
//call my database class
CodeDB() DB = new CodeDB()
[HttpGet]
public ActionResult getAll()
{
List<UserModel> viewUsers = DB.getUsers();
ViewBag.users = viewUsers
return View();
}
in the view
#{
if(Viewbag.users != null)
{
foreach(UserApp.Models.UserModel u in ViewBag.users)
{
#Html.Raw( " userID : " + u.userid +" Gender : " + u.gender)
}
}
}
I think you could do. MVC Scaffolding of Crud with there Views Auto Generated
When you make your controller There's an option "MVC Controller with Views"
Then it will ask For your Model that you want to use for scaffolding which will be
"UserModel" Then just give your Controller a Name.
Now if you look at the Index View of your Controller it will have all the attributes you want and don't want.But of course, you can remove the unnecessary attributes
Hope this helps!
I am trying to implement a search panel with several checkbox to filter a table data, but i have a problem. I cant retain value of input checked after submit.
How can I solve?
My model :
public class OrdineView
{
public int anno { get; set; }
public Int32 nrOrdine { get; set; }
public string centro { get; set; }
[DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:d}")]
public DateTime? data { get; set; }
public String codice { get; set; }
public String ragsoc { get; set; }
[DisplayFormat(DataFormatString = "{0:C}")]
public Nullable<double> importo;
}
I have a Search model:
public class OrdiniSearchModel
{
public int? anno {get;set;}
public String[] Distinzione {get;set;}
}
public class OrdiniBusinessLogic
{
private NORTHWNDEntities1 db;
public OrdiniBusinessLogic()
{
db = new NORTHWNDEntities1();
}
public IQueryable<OrdineView> GetOrdini(OrdiniSearchModel ordiniSearch)
{
var queryOrdineView = (from ordine in db.ORDINI
join cliente in db.CLIENTI on ordine.Codcli equals cliente.Codana
select new OrdineView
{
anno = ordine.Anno,
nrOrdine = ordine.Numord,
centro = ordine.Codcen,
data = ordine.Datord,
codice = ordine.Codcli,
ragsoc = cliente.Ragso1,
importo = ordine.Totord
}).ToList().AsQueryable();
var model = queryOrdineView;
if (ordiniSearch.anno != null)
{
model = model.Where(o => o.anno == ordiniSearch.anno);
}
if (ordiniSearch.Distinzione != null && ordiniSearch.distinzione.Count() > 0)
{
List<string> distinzioniSelezionate = new List<string>();
foreach (var item in ordiniSearch.Distinzione)
{
distinzioniSelezionate.Add(item);
}
model = model.Where(o => distinzioniSelezionate.Contains(o.distinzione));
}
return model;
}
}
My Controller:
public ActionResult Index(OrdiniSearchModel searchModel, int? pageNumber )
{
ViewBag.Anno = db.ORDINI.Select(o => new { o.Anno }).Distinct().OrderByDescending(o => o.Anno).Select(o => o.Anno);
var searchLogic = new OrdiniBusinessLogic();
var model = searchLogic.GetOrdini(searchModel);
return View(model.OrderBy(i => i.codice).ToPagedList(pageNumber ?? 1, 10));
}
In my view I have
<input name="Distinzione" type="checkbox" value="001">001
<input name="Distinzione" type="checkbox" value="002">002
...and so on
After submit I get data correctly but lose checked state.
UPDATE: Based on the comments, I updated the view and adde more code.
If you mean that the checkboxes don't stay checked after the page is refreshed. It's because you don't tell them which should be checked. There is one possible solution for you. Create a simple helper method right in the view where you need the checkboxes. This method just checks the array of values and if it finds the value there, it will render a checkbox with checked state.
View.cshtml
#model OrdinePagedList
#MyCheckbox("001")
#MyCheckbox("002")
#helper MyCheckbox(string value)
{
if (Model.Distinzione.Contains(value))
{
<input type="checkbox" name="Distinzione" value="#value" checked="checked"/>
}
else
{
<input type="checkbox" name="Distinzione" value="#value" />
}
#value
}
I suggest to create a new view model class:
public class OrdinePagedList
{
public IEnumerable<OrdiniView> Pages { get; set; }
public IEnumerable<string> Distinzione { get; set;
}
And update either your business logic so that it returns this new class
// from
public IQueryable<OrdineView> GetOrdini(OrdiniSearchModel ordiniSearch)
// to
public OrdinePagedList GetOrdini(OrdiniSearchModel ordiniSearch)
or update the controller:
public ActionResult Index(OrdiniSearchModel searchModel, int? pageNumber )
{
ViewBag.Anno = db.ORDINI.Select(o => new { o.Anno }).Distinct().OrderByDescending(o => o.Anno).Select(o => o.Anno);
var searchLogic = new OrdiniBusinessLogic();
var pages = searchLogic.GetOrdini(searchModel);
OrdinePagedList model = new OrdiniPagedList {
Pages = pages.OrderBy(i => i.codice).ToPagedList(pageNumber ?? 1, 10),
Distinzione = searchModel.Distinzione
}
return View(model);
}
or if you don't want (or can't) create the new view model (but I strongly recommend to do so). You can use ViewBag to pass the additinal collection of checked values:
public ActionResult Index(OrdiniSearchModel searchModel, int? pageNumber)
{
ViewBag.Distinzione = searchModel.Distinzione;
// original code
}
and then you'll just have to update the helper method. For the sake of simplicity I don't check if the ViewBag.Distinzione exists. But you should.
#helper MyCheckbox(string value)
{
if (ViewBag.Distinzione.Contains(value))
{
<input type="checkbox" name="Distinzione" value="#value" checked="checked"/>
}
else
{
<input type="checkbox" name="Distinzione" value="#value" />
}
#value
}
In short. You need to make sure that the data (collection of checked values), you get in controller, are being sent back to the view.
List<string> distinzioniSelezionate = new List<string>();
if (searchModel.distinzione != null && searchModel.distinzione.Count() > 0)
{
foreach (var item in searchModel.distinzione)
{
distinzioniSelezionate.Add(item);
}
}
OrdinePagedList model = new OrdinePagedList
{
Pages = pages.OrderBy(i => i.Codice).ToPagedList(pageNumber ?? 1, 10),
Distinzione = distinzioniSelezionate
};
I had to modify the ActionResult because Distinzione is not empty
Im a bit new at mvc, and i dont find out what am i miss. When i launch the login, in the view at foreach (var item in Model) <- the Model gets null, and stops with a System.NullReferenceException. A dont really have a clue why, and i hope somebody can give some advice what's wrong with the following code or where to start looking for the error.
The model:
public class LoginModels
{
public string UserLogin { get; set; }
public string Address { get; set; }
public string Password { get; set; }
public List<string> emailSubject { get; set; }
}
The controller:
public ActionResult Login(string address, string password, LoginModels model)
{
using (Imap imap = new Imap())
{
try
{
imap.ConnectSSL("imap.gmail.com");
imap.Login(address, password);
imap.SelectInbox();
List<long> uids = imap.Search(Flag.All);
model.emailSubject = new List<string>();
foreach (long uid in uids)
{
var eml = imap.GetMessageByUID(uid);
IMail email = new MailBuilder().CreateFromEml(eml);
model.emailSubject.Add(email.Subject);
}
Session["user"] = new LoginModels() { UserLogin = address, Address = address };
return RedirectToAction("Index", "Home", model.emailSubject);
}
catch (Exception e)
{
ViewBag.exceptionMessage = e;
return View("LoginFailed");
}
}
The view:
#using TheOnlineArchivator.Models;
#model List<TheOnlineArchivator.Models.LoginModels>
#{
ViewBag.Title = "Home";
}
#{
var user = Session["user"] as LoginModels;
if (user != null)
{
<h2>You are logged on as #user.Address</h2>
<table>
#foreach (var item in Model)
{
foreach (var elem in item.emailSubject)
{
<tr>
<td>#elem</td>
</tr>
}
}
</table>
}
}
It looks like you forgot to pass an instance of List<TheOnlineArchivator.Models.LoginModels> to the view when you rendered this view inside your controller action. What you have shown so far is your Login controller action but you didn't show us your Home/Index action. Inside this action you should make sure that you are passing a non-null model to the view:
public class HomeController : Controller
{
public ActionResult Index()
{
List<LoginModels> model = ... go get your model from somewhere and make sure it is not null
return View(model);
}
}
I'm trying to add data to a Many-To-Many relationship.
Here's my controller
[HttpPost]
public ActionResult AddSkillsPost()
{
int Teacher_ID = Convert.ToInt32(Session["Teacher_ID"]);
var SkillsArray = Request.Form["chk_group[]"];
if(SkillsArray != null)
{
foreach(var skill in SkillsArray)
{
int Skill_ID = Convert.ToInt32(skill);
var SkillToBeModified = (from s in db.Skills
where s.ID == Skill_ID
select new Skill { ID = s.ID, SkillName = s.SkillName, Teachers = s.Teachers });
var Teacher = (from t in db.Teachers
where t.ID == Teacher_ID
select new Teacher { ID = t.ID, FirstName = t.FirstName, LastName = t.LastName,
Email = t.Email, Campus = t.Campus, Skills = t.Skills });
SkillToBeModified.Teachers.Add(Teacher);
db.Entry(SkillToBeModified).State = EntityState.Modified;
db.SaveChanges();
}
}
return RedirectToAction("MyProfile");
}
So I'm trying to add a teacher to a certain skill. However, I'm having a problem with this line
SkillToBeModified.Teachers.Add(Teacher);
I get the error
'IQueryable' does not contain a definition for 'Teachers' and
no extension method 'Teachers' accepting a first argument of type
'IQueryable' could be found (are you missing a using directive
or an assembly reference?)
I'm assuming this is a syntax mistake (something with the query?), but I can't figure out the correct way to write it.
Here's my model for Skills
[Table("Skills")]
public class Skill
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Required]
public string SkillName { get; set; }
public virtual List<Teacher> Teachers { get; set; }
public Skill()
{
this.Teachers = new List<Teacher>();
}
}
and here's how my DB looks like
Looking forward to any reply's
EDIT: the form,
<form name="addSkillsForm" action="AddSkillsPost" method="post">
#foreach (var skill in Model.Skills)
{
<input type="checkbox" name="chk_group[]" value="#skill.ID" />#skill.SkillName< br />
}
<input type="submit" value="Update Skills" />
</form>
I'm using a check box form where users can check multiple items, maybe I'm not handeling them coorectly in my POST?
If your DB looks like the picture, you should be able to just do this.
[HttpPost]
public ActionResult AddSkillsPost()
{
int teacher_ID = Convert.ToInt32(Session["Teacher_ID"]);
var SkillsArray = Request.Form["chk_group[]"];
if (SkillsArray != null)
{
foreach (var skill in SkillsArray.Split(','))
{
int skill_ID = Convert.ToInt32(skill);
db.TeacherSkills.Add(new TeacherSkill() { Teacher_ID = teacher_ID, Skill_ID = skill_ID });
db.SaveChanges();
}
}
return RedirectToAction("MyProfile");
}
however if you're adding teacher to a skill then you'd do this.
[HttpPost]
public ActionResult AddSkillsPost()
{
var teacher_ID = Convert.ToInt32(Session["Teacher_ID"]);
var SkillsArray = Request.Form["chk_group[]"];
if (SkillsArray != null)
{
var teacher = db.Teachers.Find(teacher_ID);
foreach (var skill in SkillsArray.Split(','))
{
var skill_ID = Convert.ToInt32(skill);
var skillToBeModified = db.Skills.Find(skill_ID);
skillToBeModified.Teachers.Add(teacher);
db.Entry(skillToBeModified).State = EntityState.Modified;
db.SaveChanges();
}
}
return RedirectToAction("MyProfile");
}
I'm kind of new to razor MVC, and I'm wondering how can I read the values I return in the view?
My code is like this:
public ActionResult Subject(int Category)
{
var db = new KnowledgeDBEntities();
var category = db.categories.Single(c => c.category_id == Category).name;
var items = from i in db.category_items
where i.category_id == Category
select new { ID = i.category_id, Name = i.name };
var entries = from e in db.item_entry
where items.Any(item => item.ID == e.category_item_id)
select new { ID = e.category_item_id, e.title };
db.Dispose();
var model = new { Name = category, Items = items, Entries = entries };
return View(model);
}
Basically, I return an anonymous type, what code do I have to write to read the values of the anonymous type in my view?
And if this is not possible, what would be the appropriate alternative?
Basically, I return an anonymous type
Nope. Ain't gonna work. Anonymous types are emitted as internal by the compiler and since ASP.NET compiles your views into separate assemblies at runtime they cannot access those anonymous types which live in the assembly that has defined them.
In a properly designed ASP.NET MVC application you work with view models. So you start by defining some:
public class MyViewModel
{
public string CategoryName { get; set; }
public IEnumerable<ItemViewModel> Items { get; set; }
public IEnumerable<EntryViewModel> Entries { get; set; }
}
public class ItemViewModel
{
public int ID { get; set; }
public string Name { get; set; }
}
public class EntryViewModel
{
public int ID { get; set; }
public string Title { get; set; }
}
and then you adapt your controller action to pass this view model to the view:
public ActionResult Subject(int Category)
{
using (var db = new KnowledgeDBEntities())
{
var category = db.categories.Single(c => c.category_id == Category).name;
var items =
from i in db.category_items
where i.category_id == Category
select new ItemViewModel
{
ID = i.category_id,
Name = i.name
};
var entries =
from e in db.item_entry
where items.Any(item => item.ID == e.category_item_id)
select new EntryViewModel
{
ID = e.category_item_id,
Title = e.title
};
var model = new MyViewModel
{
CategoryName = category,
Items = items.ToList(), // be eager
Entries = entries.ToList() // be eager
};
return View(model);
}
}
and finally you strongly type your view to the view model you have defined:
#model MyViewModel
#Model.Name
<h2>Items:</h2>
#foreach (var item in Model.Items)
{
<div>#item.Name</div>
}
<h2>Entries:</h2>
#foreach (var entry in Model.Entries)
{
<div>#entry.Title</div>
}
By the way to ease the mapping between your domain models and view models I would recommend you checking out AutoMapper.
Oh, and since writing foreach loops in a view is kinda ugly and not reusable I would recommend you using display/editor templates which would basically make you view look like this:
#model MyViewModel
#Model.Name
<h2>Items:</h2>
#Html.DisplayFor(x => x.Items)
<h2>Entries:</h2>
#Html.DisplayFor(x => x.Entries)
and then you would define the respective display templates which will be automatically rendered for each element of the respective collections:
~/Views/Shared/DisplayTemplates/ItemViewModel:
#model ItemViewModel
<div>#item.Name</div>
and ~/Views/Shared/DisplayTemplates/EntryViewModel:
#model EntryViewModel
<div>#item.Title</div>