I am trying to lower the role of a user by clicking a link in my view.
When I click the link, it doesn't go to the action, but it just gives 404 error and links the resource that is not found with the string I am trying to pass to the action( referred to as "stringparameter")
In this case, the link is /Admin/Disable/stringparameter
I think I am not using the correct overload, so could someone help me out?
Thanks
This is the action in the AdminController
[HttpPost]
public ActionResult Disable(string id)
{
Role rol = new UserRepository().GetRole("Disabled");
new UserRepository().UpdateUser(id,rol.RoleId);
return RedirectToAction("Users");
}
this is the viewmodel
public class UserSuperUserPM
{
public UserClass User { get; set; }
public List<UserClass> Users { get; set; }
public UserClass SuperUser { get; set; }
public List<UserClass> SuperUsers { get; set; }
public UserClass Disabled { get; set; }
public List<UserClass> Disableds { get; set; }
public UserClass Inactive { get; set; }
public List<UserClass> Inactives { get; set; }
}
this is the userclass
public class UserClass
{
public string UserId { get; set; }
public string Username { get; set; }
public string Role { get; set; }
}
and this is the view(1 of the 4 similar tables in the view)
#foreach (var item in Model.Users)
{
<tr>
<td class="col-md-4">
#Html.DisplayFor(modelItem => item.Username, Model.Users)
</td>
<td class="col-md-4">
#Html.DisplayFor(modelItem => item.Role, Model.Users)
</td>
<td calss="col-md-4">
--------Commented attempted links(none of them work correct)
#*#Html.ActionLink("Disable", "Disable", new { Controller = "Admin", action = "Disable", id = item.UserId })*#
#*Disable*#
#*#Html.ActionLink("Disable","Admin", new { id = item.UserId },null)*#
#*#Html.ActionLink("Disable", "Disable","Admin", item.UserId)*#
-------original attempted link
#Html.ActionLink("Disable", "Disable", new { id = item.UserId})
</td>
</tr>
}
It's because href attr in a a element just do GET dont POST, so to it works change the Action to :
[HttpGet]
public ActionResult Disable(string id)
{
Role rol = new UserRepository().GetRole("Disabled");
new UserRepository().UpdateUser(id,rol.RoleId);
return RedirectToAction("Users");
}
But I suggest to you do this with JS.
Just delete [HttpPost] it says that this controller only can be access by POST method an you are trying to access by GET, you should let it post and do the call with AJAx
Related
I am trying to pull all the USERS created in the database(AspNetUsers) using Register form.
I have read several similar issues but can't fix this issue.Usually the reason for this error is when we try to pull a list from the controller but in view we do not specify IEnumerable at top.However I have added that as well , please see the code below. Million thanks for any help in advance.
#model IEnumerable<TimeSheet.ViewModel.UserViewModel>
#using TimeSheet.Models
#{
ViewBag.Title = "Index";
}
<h2>Manage User</h2>
<br/>
<table class="table table-condensed table-hover">
<tr class="table-header">
<th>
#Html.DisplayNameFor(m => m.Email)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(m => item.Email)
</td>
<td>
#Html.Partial("_TableButtonPartial", new IndividualButtonPartial { UserId = item.Id })
</td>
</tr>
}
</table>
UserController
public class UserController : Controller
{
TimeSheetEntities db = new TimeSheetEntities();
/* private ApplicationDbContext db;
public UserController()
{
db = ApplicationDbContext.Create();
}*/
// GET: User
public ActionResult Index()
{
return View(db.AspNetUsers.ToList());
//return View();
}
}
UserViewModel
namespace TimeSheet.ViewModel
{
public class UserViewModel
{
[Required]
public string Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
public string FullName { get { return this.FirstName + " " + this.LastName; } }
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.Password)]
public string ConfirmPassword { get; set; }
public string UserRole { get; set; }
public string Manager { get; set; }
}
}
Since your are using mostly email,the easiest way to fix would be to change a model class
#model List<AspNetUser>
or if you want to save some network traffic, you can go a long way
create this viewmodel
public class UserGridViewModel
{
public string Id { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
}
fix the action
public ActionResult Index()
{
var model= db.AspNetUsers.Select(i=> new UserGridViewModel {
Id=i.Id,
Email=i.Email
}).ToList();
return View(model);
}
and view
#model List<TimeSheet.ViewModel.UserGridViewModel>
There are 2 models. The user is logging into the system. I want a value from the current model to be added to the logged in user's table when he clicks the button in the Forum View. Ogrenci Model enters the system. When the button is clicked, I want ProjectName to be added to the BekleyenProje column in the Ogrenci Model. How can I do that?
Model 1:
public class Ogrenci
{
public int OgrenciID { get; set; }
public int OgrenciNumarasi { get; set; }
public string Ad { get; set; }
public string Soyad { get; set; }
public string Bolum { get; set; }
public short Sinif { get; set; }
public string Yetenekler { get; set; }
public string Sifre { get; set; }
public string BekleyenProje { get; set; }
public string OnaylananProje { get; set; }
//FK
public List<Proje> Projeler { get; set; }
}
Model 2:
public class Proje
{
public int ProjeID { get; set; }
public string ProjeAdi { get; set; }
public string Aciklama { get; set; }
public DateTime EklenmeTarihi { get; set; }
//FK
public int OgrenciID { get; set; }
public Ogrenci Ogrenci { get; set; }
}
ForumController:
public class ForumController : Controller
{
private OgrenciContext db = new OgrenciContext();
// GET: Forum
public ActionResult Index()
{
//Include(o => o.Ogrenci) -- öğrenci bilgilerini dahil ediyoruz
return View(db.Projeler.Include(o => o.Ogrenci).ToList());
}
}
Forum Index View (The button I'm talking about is here):
#model IEnumerable<DonemProjesi.Models.Proje>
#{
ViewBag.Title = "Index";
}
<table class="table table-striped table-bordered table-hover table-condensed cols-3 custom_table">
<thead>
<tr>
<th scope="col">Proje</th>
<th scope="col">Etkileşimler</th>
<th scope="col">Yayınlanma Tarihi</th>
<th scope="col">Detay</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
<div>#Html.DisplayFor(modelItem => item.ProjeAdi)</div>
<small>#Html.DisplayFor(modelItem => item.Ogrenci.Ad)</small>
</td>
<td>
<ul class="activity_outer">
<li><strong>03</strong><span>Başvuranlar</span></li>
<li><strong>01</strong><span>Dahil olanlar</span></li>
</ul>
</td>
<td>
<div class="last_activity"><span class="time_ago">#Html.DisplayFor(modelItem => item.EklenmeTarihi)</span></div>
</td>
<td>
<button type="button" class="login-button">#Html.ActionLink("Proje Detayı", "Details", "Proje", new { id = item.ProjeID }, new { #class = "detayy" })</button>
<button type="button" class="login-button"></button> //BUTTON IS HERE
</td>
</tr>
}
</tbody>
Also, Controller for Login:
public class SecurityController : Controller
{
OgrenciContext db = new OgrenciContext();
// GET: Security
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(Ogrenci ogrenci)
{
var kullanici = db.Ogrenciler.FirstOrDefault(x=>x.OgrenciNumarasi == ogrenci.OgrenciNumarasi && x.Sifre == ogrenci.Sifre);
if (kullanici!=null)
{
FormsAuthentication.SetAuthCookie(kullanici.Ad, false);
Session.Add("OgrenciID", kullanici.OgrenciID); //kimlik doğrulamasu yapılan kullanıcının ID'si alınıyor
return RedirectToAction("Details","Ogrenci", new {#id=kullanici.OgrenciID });
}
else
{
ViewBag.Mesaj = "Geçersiz numara veya şifre girdiniz!";
return View();
}
}
}
It's better to use repository pattern, but a direct solution would be:
kullanici.BekleyenProje = Request["ProjectName"];
db.SaveChanges();
Also it depends on how many properties you want to pass. If it's only one, you can send it in the Request. Otherwise, you create a view model with the necessary members.
Make sure the button is submitting the form and ProjectName is a hidden field inside the form.
Currently i'm able to show all column in razer view from userRole model.
Just curious if i like to show the SiteName column in UserRole Razor view, instead of showing SiteID, is it possible? I know it can be done via custom view model, but is it a must? Please correct me if i'm wrong!
UserRole Model:
public int UserID { get; set; }
public string UserName { get; set; }
public int SiteID { get; set; }
*No SiteName column here....so i only can show SiteID in razor..
Site Model :
public int SiteID { get; set; }
public string SiteName { get; set; } <<-- the column i want..
Controller:
public ActionResult Index()
{
//need join table here perhaps?
return View(db.User_Role.ToList());
}
Razor View:
#model IEnumerable<FAB_Portal_POC.Models.UserRole>
<table class="table table-striped table-hover">
<tr>
<th>
#Html.DisplayNameFor(model => model.UserName)
</th>
<th>
#Html.DisplayNameFor(model => model.Role)
</th>
<th>
#Html.DisplayNameFor(model => model.SiteID)
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.UserName)
</td>
<td>
#Html.DisplayFor(modelItem => item.Role)
</td>
<td>
#Html.DisplayFor(modelItem => item.SiteID) <<-- i want site name.
</td>
</tr>
}
</table>
The first problem is that your UserRole entity model doesn't seem to have a navigation property.
You don't need to, but then querying becomes awkward:
var rolesWithSite = from r in db.User_Role
join s in db.Sites on s.ID equals r.Site_ID
select new
{
Role = r,
Site = s
}
.ToList();
While when you add a navigation property (perhaps even instead of the foreign key property):
public class User_Role
{
public int UserID { get; set; }
public string Role { get; set; }
public string UserName { get; set; }
public virtual Site Site { get; set; }
}
Querying will become a whole lot easier:
var rolesWithSite = db.User_Role.Include(r => r.Site).ToList();
You can then introduce a viewmodel:
public class UserRoleViewModel
{
public int UserID { get; set; }
public string UserName { get; set; }
public string Role { get; set; }
public string Site { get; set; }
}
And map the query results to that:
var viewModels = rolesWithSite.Select(r => new UserRoleViewModel
{
UserID = r.UserID,
UserName = r.UserName,
Role = r.Role,
Site = r.Site.SiteName,
}).ToList();
return View(viewModels);
Entities and Models are very different.
You have to create a specific model for your page.
something like this :
PageModel
public string UserName { get; set; }
public string SiteName { get; set; }
In your controller your have to prepare all the data you want to send to the page. It s here that you will "associate" your entities to your pagemodel
public ActionResult Index()
{
var roles = db.User_Role.ToList();
var sites = db.Sites.ToList(); // i don t know how you get this information in your exemple.
//define here every property of the PageModel you want to use there
var model = new PageModel();
model.UserName = roles.UserName;
model.SiteName = sites.Select(...).SiteName;
return View(model);
}
then in razor view
#model IEnumerable<FAB_Portal_POC.Models.PageModel>
Hope it will help
You have multiple ways to do that the simple one is you have to create new class name UserRoleViewData and mention these fields and pass the class object to view. just like that.
New Class UserRoleViewData Look like this
public int UserID { get; set; }
public string UserName { get; set; }
public int SiteID { get; set; }
public string SiteName { get; set; }
and your Controller
public ActionResult Index()
{
List<className> dto = (from a in _db.User_Role
join b in db.Site on a.SiteID equals b.SiteID
select (new classname { UserID =a.UserID , UserName =a.UserName , SiteID =a.SiteID , SiteName =b.SiteName })).ToList();
return View(dto);
}
In View You have to change #model IEnumerable<FAB_Portal_POC.folderName.ClassName>
and map other property on view like others.I hope u'll understand and this will help you.
You can store the sites list in the ViewBag and show the site name by extracting it from the ViewBag:
public ActionResult Index()
{
ViewBag.Sites = db.Sites.ToList();
return View(db.User_Role.ToList());
}
And the View:
<td>
#Html.DisplayFor(modelItem => ViewBag.Sites.Single(s => s.SiteID == item.SiteID).SiteName)
</td>
Another, and to me a better approach, would be to create a ViewModel for your view which contains all of the data that you need. And return that view model to your view.
public class UserSiteViewModel
{
public int UserID { get; set; }
public string UserName { get; set; }
public string Role { get; set; }
public int SiteID { get; set; }
public string SiteName { get; set; }
}
No need to use ViewBag , join between 2 tables and store result in another viewModel it's vary bad idea. Please check out reference link, It will really help you to do Code in Very good direction. Click Here
When passing the model from my view to my controller, the data is all null. I was able to successfully pass it using an ActionLink but I don't think that is the best way; for security reasons (I do not want sensitive data in the querystring).
My models
public class DashboardModel
{
// Dasboard quick numbers
public int TotalUsers { get; set; }
public int TotalUnauthUsers { get; set; }
public int GamesPlayed { get; set; }
public int AssociatedGroups { get; set; }
public int TotalGroups { get; set; }
// Dashboard table
public IEnumerable<ManageUserData> UnauthUsers { get; set; }
}
public class ManageUserData
{
public string UserName { get; set; }
public int AlternateId { get; set; }
public string Email { get; set; }
public string Role { get; set; }
public IEnumerable<string> InvestigatorGroups { get; set; }
public string Institution { get; set; }
// User status
public bool AccountLocked { get; set; }
public bool EmailConfirmed { get; set; }
}
Snippet of my view
#model TestGame.ViewModels.DashboardModel
#foreach (var user in Model.UnauthUsers)
{
<tr>
<td>#user.UserName</td>
<td>#user.AlternateId</td>
<td>#user.Email</td>
<td>#user.Role</td>
<td>
#if (!user.EmailConfirmed)
{
<div class="text-warning">Unconfirmed Email</div>
}
#if (user.AccountLocked)
{
<div class="text-danger">Account Locked</div>
}
</td>
<td>
#if (user.AccountLocked || !user.EmailConfirmed)
{
using (Html.BeginForm("Manage", "Admin", FormMethod.Post))
{
#Html.HiddenFor(x => user.UserName)
#Html.HiddenFor(x => user.Email)
<input type="submit" value="Manage" />
You have to make sure the path starts with the object being posted back; what you have will work great if the action being posted to (HttpPost Admin/Manage action) takes an object of type User; if it takes an object of the model type, change your form to the following:
for (var i = 0; i < Model.UnAuthUsers.Count; i++)
using (Html.BeginForm("Manage", "Admin", FormMethod.Post))
{
#Html.HiddenFor(x => x.UnAuthUsers[i].UserName)
#Html.HiddenFor(x => x.UnAuthUsers[i].Email)
<input type="submit" value="Manage" />
Creating a reference from the model (being x) will do the trick.
EDIT: Based on comments, add two properties to your model:
public class DashboardModel
{
public string SelectedUserName { get; set; }
public string SelectedEmail { get; set; }
}
In your form, render a hidden for for that name; I've had trouble using HiddenFor, so I've in the past used the hidden directly:
using (Html.BeginForm("Manage", "Admin", FormMethod.Post))
{
<input type="hidden" name="#Html.NameFor(i => i.SelectedUserName)" value="#Model.UnauthUsers[i].UserName" />
<input type="hidden" name="#Html.NameFor(i => i.SelectedEmail)" .. />
And upon submitting the form, the user from that form will be posted back via the model, via these new properties.
Hi; i have 2 dropdownlist. one is customers ddl another one is jobs. i want to keep alive selected value after any selection process. But i can not.
i want to keep selected value on ddl'selected item After click button. (i have been used 2 methods: dropdownlist and dropdownlistfor.) My favorite articles are http://stackoverflow.com/questions/6981698/how-to-keep-dropdownlist-selected-value-after-postback
and
http://stackoverflow.com/questions/4950798/how-to-post-the-selected-value-of-a-selectlist-to-the-controller-using-a-view-mo
ViewModel:
public class MyViewModel
{
public IEnumerable<string> Columns { get; set; }
public IEnumerable<dynamic> Values { get; set; }
public bool HasNext { get; set; }
public bool HasPrevious { get; set; }
public IEnumerable<CustomerModel> Customers { get; set; }
public IEnumerable<SelectListItem> Jobs { get; set; }
}
Cotroller:
public class JobController : Controller
{
public ActionResult Index(int? page)
{
var model = new MyViewModel();
model.Customers = CustomerOperation.GetCustomers().Items;
ViewData["Jobs"] = new SelectList(JobOperation.GetCustomersAssemblyList().Items, "scheduleId", "name", null);
return View(model);
}
View:
<table style="padding:25px; margin:10px 10px 10px 10px; width:800px" id="sample">
<tr>
<td>Customer Name: </td>
<td>
<%= Html.DropDownListFor(X=>X.Customers,new SelectList(Model.Customers,"Id","Name"),"** Please Select **", new { id = "ddlCustomers" })%>
</td>
<td>Job Name:</td>
<td>
<%= Html.DropDownList("Jobs", (IEnumerable<SelectListItem>)ViewData["Jobs"], "** Please Select **", new { id = "ddlJobs", disabled = "disabled" })%>
</td>
<td>
<input value="monitor" name="submitButton" type="submit" />
</td>
</tr>
</table>
Your model should be something like this
public class MyViewModel
{
public IEnumerable<string> Columns { get; set; }
public IEnumerable<dynamic> Values { get; set; }
public bool HasNext { get; set; }
public bool HasPrevious { get; set; }
public IEnumerable<CustomerModel> Customers { get; set; }
public IEnumerable<SelectListItem> Jobs { get; set; }
public CustomerModel Customer {get; set;}
}
In your view the code to add dropdown should be something like this
<%= Html.DropDownListFor(X=>X.Customer,Model.Customers) %>
Hope this helps.