I'm beginner in ASP NET and I don't know how to select object from list for example I have static data in my model:
namespace ProjectMVC.Models
{
public class Initializer
{
public List<Profile> GetProfiles()
{
var profile = new List<Profile>(){
new Profile {
Id = 2,
Name = "Henrik Crawford",
SportType = "Спортсмен",
Location = "Украина, Кременчуг"
},
new Profile {
Id = 3,
Name = "Diane McCartney",
SportType = "Спортсмен",
Location = "Украина, Кременчуг"
},
new Profile {
Id = 4,
Name = "William Jenkins",
SportType = "Спортсмен",
Location = "Украина, Кременчуг"
},
};
return profile;
}
}
And I have ajax request which send an Id of user. For this I have actionresult in controller:
namespace ProjectMVC.Controllers
{
public class HomeController : Controller
{
private readonly Initializer init = new Initializer();
public ActionResult AddUserAjax(int UserId)
{
List<Profile> SomeList = init.GetProfiles();
// here I want to select and return user from list , where UserId == Id from list in model
}
}
This should do:
var user = SomeList.FirstOrDefault(u => u.Id == UserId)
It's utilising LINQ which is very powerful for querying objects.
You can just use Where or FirstOrDefault if you want to get one user:
var user = SomeList.FirstOrDefault(u => u.Id == UserId);
Related
I have three tables
dbo.PermissionFunc, dbo.Roles, dbo.Permissions for my asp.net MVC web application.
dbo.PermissionFunc contains all the function name in my project.
dbo.Roles contains the user roles such as admin, user, subuser etc
dbo.Permissions contains the RolesId from dbo.Roles and PermissionFuncId from dbo.PermissionFunc.
I want to give authorization based on the value assigned in dbo.Permission.
Update in question:
Query using to determine if the current user has permission or not
string mail = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
var usr = _user.GetUserByMail(mail);
var permFunc = _permissionfunc.FindByName("ActionResultName");
var permission = _permission.checkIfPermitted(Convert.ToInt64(usr.Usr_Role_ID), permFunc.PermFunc_ID);//usr.Usr_Role_ID is RoleId and permFunc.PermFunc_ID is the PermissionFunctionId
if(permission != null)
{
//Permission granted
}
else
{
//Permission Rejected
}
Thanks in advance
You can create custom AuthorizationAttribute with the logic of checking your roles and permissions in it and use it for operations that requires that.
You can use mvc.filters with your implementation of IAuthorizationFilter, to filter every request. Register it in your FilterConfig
filters.Add(new MyAuthorizationAttribute());
Updated to use CustomAuthorize attribute on MVC action
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class CustomAuthorize : AuthorizeAttribute
{
private string _action { get; set; }
public CustomAuthorize() { }
public CustomAuthorize(string action) { _action = action; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.User == null)
return false;
if (!httpContext.User.Identity.IsAuthenticated)
return false;
// HasPermission function implements looking up by user name and action
// to see if user has a role that would give them access to this action
return PermissionChecker.HasPermission(httpContext.User.Identity.Name, _action);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// handle unauthorized requests here
// return 503 error or whatever
}
}
// example of using custom attribute in MVC controller action
[HttpGet]
[CustomAuthorize("View")]
public ActionResult MyActionActualViewMethodName()
{
var result = {
id = 1,
name = ""
};
return Json(result);
}
[HttpDelete]
[CustomAuthorize("Delete")]
public ActionResult MyActionActualDeleteMethodName(int id)
{
// do delete action
return Json(true);
}
// static permission checker implementation
public static class PermissionChecker
{
static List<GenericIdNameClass> users = new List<GenericIdNameClass>() {
new GenericIdNameClass { Id = 1, Name = "John" },
new GenericIdNameClass { Id = 2, Name = "Bob" },
};
static List<GenericIdNameClass> roles = new List<GenericIdNameClass>() {
new GenericIdNameClass { Id = 10, Name = "User" },
new GenericIdNameClass { Id = 11, Name = "Admin" },
};
static List<GenericIdNameClass> actions = new List<GenericIdNameClass>() {
new GenericIdNameClass { Id = 100, Name = "View" },
new GenericIdNameClass { Id = 101, Name = "Create/Edit" },
new GenericIdNameClass { Id = 102, Name = "Delete" },
};
static List<GenericEntityRelationClass> roleActionMappings = new List<GenericEntityRelationClass>() {
new GenericEntityRelationClass{ Id1 = 10, Id2 = 100 },
new GenericEntityRelationClass{ Id1 = 11, Id2 = 100 },
new GenericEntityRelationClass{ Id1 = 11, Id2 = 101 },
new GenericEntityRelationClass{ Id1 = 11, Id2 = 102 },
};
// John only has User role, Bob has User and Admin
static List<GenericEntityRelationClass> userRoleMappings = new List<GenericEntityRelationClass>() {
new GenericEntityRelationClass{ Id1 = 1, Id2 = 10 },
new GenericEntityRelationClass{ Id1 = 2, Id2 = 10 },
new GenericEntityRelationClass{ Id1 = 2, Id2 = 11 },
};
public static bool HasPermission(string userName, string actionName)
{
var user = users.SingleOrDefault(x => x.Name == userName);
if (user == null)
return false;
var action = actions.SingleOrDefault(x => x.Name == actionName);
if (action == null)
return false;
var userRoles = userRoleMappings.Where(x => x.Id1 == user.Id).Select(x => x.Id2).ToList();
return roleActionMappings.Any(x => userRoles.Contains(x.Id1) && x.Id2 == action.Id);
}
public class GenericIdNameClass
{
public int Id { get; set; }
public string Name { get; set; }
}
public class GenericEntityRelationClass
{
public int Id1 { get; set; }
public int Id2 { get; set; }
}
}
Alsamil,
If you have time, please read about the new way Microsoft is doing Claims-Based Authorization
And if you have even more time, I really recommend you this conference. Dominick Baier & Brock Allen are really known in the security industry and they explain how to do Authorisation in a really nice way which is related to the Claims-Based Authorization article. If I am not wrong they are the minds behind this new way of authorisation.
The answer that worked for the above question is here:
AuthorizationController
#region CustomAuthorizationAttribute
public class CustomAuthorizationAttribute : AuthorizeAttribute
{
private PermissionRepository _permission = new PermissionRepository();
private PermissionFuncRepository _permissionFun = new PermissionFuncRepository();
// roles start
public string IdentityRoles
{
get { return _permissionName ?? String.Empty; }
set
{
_permissionName = value;
}
}
private string _permissionName;
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//do the base class AuthorizeCore first
if (httpContext.User.Identity.IsAuthenticated)
{
string RoleID = FormsAuthentication.Decrypt(httpContext.Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name.Split('|')[1];
var permisionID = _permissionFun.FindByName(_permissionName);
if(permisionID != null)
{
var permis = _permission.GetPermission().Where(a => a.Perm_PermFuncID == permisionID.PermFunc_ID && a.Perm_RollID.ToString() == RoleID).FirstOrDefault();
if (permis != null)
{
return true;
}
}
}
return false;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
//if the user is not logged in use the deafult HandleUnauthorizedRequest and redirect to the login page
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
//if the user is logged in but is trying to access a page he/she doesn't have the right for show the access denied page
{
filterContext.Result = new RedirectResult("~/Home/AccessDenied");
}
}
}
#endregion
Foreach ActionController, I accessed these Authorization as follows:
[CustomAuthorization(IdentityRoles = "AdjustmentsView")]
public ActionResult AdjustmentIndex()
{
var adjlist = _Adj.GetAdjustmentHead();
List<AdjustmentHeadViewModel> adjustlist = new List<AdjustmentHeadViewModel>();
foreach (var item in adjlist)
{
Mapper.Initialize(cfg => cfg.CreateMap<AdjustmentHead, AdjustmentHeadViewModel>());
AdjustmentHeadViewModel entity = Mapper.Map<AdjustmentHead, AdjustmentHeadViewModel>(item);
adjustlist.Add(entity);
}
return View(adjustlist);
}
You need to create a custom AuthorizeAttribute and tag your actions with it.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class RequireFunction : AuthorizeAttribute
{
private string _function;
public RequireFunction(string func) { _function = func; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.User == null)
return false;
if (!httpContext.User.Identity.IsAuthenticated)
return false;
// modified code sample from question
string mail = httpContext.User.Identity.Name;
var user = _user.GetUserByMail(mail);
var permFunc = _permissionfunc.FindByName(_function);
var permission = _permission.checkIfPermitted(Convert.ToInt64(usr.Usr_Role_ID), permFunc.PermFunc_ID);
return permission != null;
}
}
I have two lists:
List<UserModel> and List<UserDetails>
Where:
public class UserModel
{
public int RoleId { get; private set; }
public IEnumerable<UserType> UserType
{
get { return Enum.GetValues(typeof(UserType)).Cast<UserType>(); }
}
private UserType selectedUserType;
public UserType SelectedUserType
{
get { return selectedUserType; }
set
{
.....
}
}
}
and
public class UserDetails
{
public bool IsPrimary { get; set; }
public int RoleId { get; set; }
...
}
I need to set bool IsPrimary from UserDetails to true, if SelectedUserType is set to Primary, but only for the same RoleId... UserType is an Enum : Primary, Secondary.
So, how can i do this? Any idea?
You can iterate them by their RoleID as the following:
List<UserModel> models = ...;
List<UserDetails> details = ...;
models.Foreach(x => details
.Where(y => y.RoleId == x.RoleId)
.ToList()
.Foreach(y => y.IsPrimary = (x.SelectedUserType == UserType.Primary))
);
What it does is iterating the UserModels, than foreach UserModel iterating all of the UserDetails and filtering those who have the same RoleId, than for them setting IsPrimary to true only if SelectedUserType of the matching UserModel is UserType.Primary.
This also can be done without Linq like the following:
List<UserModel> models = ...;
List<UserDetails> details = ...;
foreach (UserModel model in models)
{
foreach (UserDetails detail in details)
{
if (detail.RoleId == model.RoleId)
{
bool isPrimary = model.SelectedUserType == UserType.Primary;
detail.IsPrimary = isPrimary;
}
}
}
I'm assuming you have an IEnumerable<UserModel> and an IEnumerable<UserDetails>. I've changed the classes a bit to simplify the question.
var userDetails = new List<UserDetails>{
new UserDetails(){ Id = 1, RoleId = 1 },
new UserDetails(){ Id = 2, RoleId = 1 },
new UserDetails(){ Id = 3, RoleId = 2 },
new UserDetails(){ Id = 4, RoleId = 2 }
};
var userModels = new List<UserModel> {
new UserModel { RoleId = 1, SelectedUserType = UserType.Primary },
new UserModel { RoleId = 2, SelectedUserType = UserType.Secondary },
new UserModel { RoleId = 3, SelectedUserType = UserType.Primary }
};
Then, you need to set IsPrimary to true of UserDetails 1 and 2, correct?
var userDetailsToSetPrimary =
(from userDetail in userDetails
join userModel in userModels
on userDetail.RoleId equals userModel.RoleId
where userModel.SelectedUserType == UserType.Primary
select userDetail);
foreach(userDetail in userDetailsToSetPrimary)
userDetail.IsPrimary = true;
You should consider joining the two lists using LINQ expressions. Convert the result of the join function (which also should be filtered based on UserType) to a new list and loop through all the elements and set the boolean to true.
Check out the following question.
I want to test the following method:
public ActionResult Index()
{
var transactions = db.Transactions.Include(t => t.User)
.GroupBy(t => t.UserId)
.Select(group => new TransactionViewModel
{
User = group.FirstOrDefault().User.FullName,
UserId = group.FirstOrDefault().UserId,
Total = (group.Sum(t => t.TransactionAmount))
});
// Show lowest balance first
return View(transactions.ToList());
}
Here the Transaction model has a list of Orders, has a foreign key to User and some more properties, see:
public class Transaction
{
public int TransactionId { get; set; }
public DateTime Date { get; set; }
public int UserId { get; set; }
public List<Order> Orders { get; set; }
public decimal TransactionAmount { get; set; }
public virtual User User { get; set; }
}
The TransactionViewModel looks as follows:
public class TransactionViewModel
{
public string User { get; set; }
public int UserId { get; set; }
public decimal Total { get; set; }
}
and is used to calculate the Total of different transactions belonging to a user.
To test this method I have a FakeDbSet and use a FakeContext (which both work in tests of other controllers) in the following Setup:
[TestClass]
public class TransactionControllerTest
{
TransactionController trController;
[TestInitialize]
public void TransactionControllerTestInitialize()
{
// Arrange
var memoryTransactionItems = new FakeDbSet<Transaction>
{
new Transaction {
Date = DateTime.Today,
TransactionAmount = 5.10M,
UserId = 1,
Orders = new List<Order>{
// Categorie 2 and confirmed
new Order { OrderId = 2,
UnitPrice = 2.00M,
Quantity = 1,
Date = DateTime.Today,
IsConfirmed = true,
User = new User {
Name = "Kees",
FullName="Kees Piet",
Email = "Kees#DeHond.nl",
isAvailable = true,
UserId = 1
},
Product = new Product {
Category = new Category {
CategoryId = 2,
Name = "Categorie2"
},
Name = "Testproduct2",
Price = 2.00M,
Visible = true
}
},
// Categorie 2 and confirmed
new Order { OrderId = 2,
UnitPrice = 1.00M,
Quantity = 1,
Date = DateTime.Today,
IsConfirmed = true,
User = new User {
Name = "Jan",
FullName="Jan Piet",
Email = "Jan#DeBouvrier.de",
isAvailable = true,
UserId = 2
},
Product = new Product {
Category = new Category {
CategoryId = 2,
Name = "Categorie2"
},
Name = "Testproduct2",
Price = 3.10M,
Visible = true
}
}
}
}
};
// Create mock units of work
var mockData = new Mock<FakeContext>();
mockData.Setup(m => m.Transactions).Returns(memoryTransactionItems);
// Setup controller
trController = new TransactionController(mockData.Object);
}
[TestMethod]
public void TestTransactionIndex()
{
// Invoke
var viewResult = trController.Index() as ViewResult;
var transactionsFromView = (IEnumerable<TransactionViewModel>)viewResult.Model;
// Assert
Assert.AreEqual(1, transactionsFromView.Count(),
"The amount of transactions added to the Index View should be 1.");
}
}
When I run the TestTransactionIndex I get the following error:
Test Name: TestTransactionIndex Test Outcome: Failed Test
Duration: 0:00:30.6276475
Result Message: Test method
Tests.Controllers.TransactionControllerTest.TestTransactionIndex threw
exception: System.NullReferenceException: Object reference not set to
an instance of an object. Result StackTrace: at lambda_method(Closure
, IGrouping2 ) at
System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at
Controllers.TransactionController.Index()
I find this strange since I setup my mock units in the proper way. I hope someone can explain how I can properly send the FakeDbSet<Transaction> to the view and not get a NullReferenceException.
/Edit As requested, here are the contructors for TransactionController:
private IContext _context;
public TransactionController()
{
_context = new Context();
}
public TransactionController(IContext context)
{
_context = context;
}
The query in your index method includes the line:
db.Transactions.Include(t => t.User)
And the Select part of the query is using the User property in the Transaction class to populate the TransactionViewModel as in
User = group.FirstOrDefault().User.FullName,
That line will throw a NullReferenceException if the User property in the Transaction is null. So you need the result of that query to contain a not null User property when executed in your unit test using the fake objects.
I am not sure how your fake context and DbSets work, but the easiest thing to try is to populate the User property of the Transactions in your fake memoryTransactionItems.
You may also try adding a fake users dbset as in the next code snippet (I'm assuming you have a Users DbSet in your EF context):
var memoryUsers = new FakeDbSet<User>
{
new User{ UserId = 1, ... },
...
};
mockData.Setup(m => m.Users).Returns(memoryUsers);
I have an entity called ActionResult that my methods along the application returns. Now i want to map a returned object in the ActionResult to it's right place in an array of that object...
public class Core
{
public Employee[] Employees = new[] {
new Employee {
Name = "Jack",
Age = 21,
Salary = 1000
},
new Employee {
Name = "Carl",
Age = 35,
Salary = 1000
},
new Employee {
Name = "Tom",
Age = 41,
Salary = 1000
},
};
}
public class ActionResult
{
public string ActionID { get; set; }
public Employee Employee { get; set; }
}
public class Employee
{
public String Name { get; set; }
public int? Age { get; set; }
public int? Salary { get; set; }
public int? Level { get; set; }
}
public ActionResult MethodThatReturnsActionResultWithAnEmployee()
{
return new ActionResult {
ActionID = new Guid().ToString(),
Employee = new Employee {
Name = "Carl",
Age = 35,
Salary = 7000,
Level = 1
}
};
}
Now as you can see what i want to do is taking the Employee that is returned from the Method, and search in the array of Employees in the Core and update it using the new given data using AutoMapper.
AutoMapper will not search employee in some array for you. How it would know which employees should be considered as equal? You should search for employee manually, and use appropriate mapping method to update existing instance of employee with data from other employee instance:
Mapper.CreateMap<Employee, Employee>();
var result = MethodThatReturnsActionResultWithAnEmployee();
var employee = result.Employee;
var core = new Core();
var employeeToUpdate =
core.Employees.FirstOrDefault(e => e.Name == employee.Name);
Mapper.Map(employee, employeeToUpdate);
If you really want mapping to look like
Mapper.Map(result, core);
Then you should write your own type mapper for this:
public class ActionResultToCoreConverter : ITypeConverter<ActionResult, Core>
{
public Core Convert(ResolutionContext context)
{
var result = (ActionResult)context.SourceValue;
var employee = result.Employee;
var core = (Core)context.DestinationValue ?? new Core();
var employeeToUpdate =
core.Employees.FirstOrDefault(e => e.Name == employee.Name);
Mapper.Map(employee, employeeToUpdate);
return core;
}
}
And mapping will look like:
Mapper.CreateMap<Employee, Employee>(); // this map also required
Mapper.CreateMap<ActionResult, Core>()
.ConvertUsing<ActionResultToCoreConverter>();
var result = MethodThatReturnsActionResultWithAnEmployee();
var core = new Core();
Mapper.Map(result, core);
// if you want to create new Core instanse:
var core2 = Mapper<Core>(result);
I am attempting to Query a database and store those results in a model, one of the columns is numerical and one is string data:
Model:
using System.Data.Entity;
namespace Portal.Models
{
public class CompanyListId
{
public int Id { get; set; }
public string CompanyName { get; set; }
}
public class CompanyListIdDbContext : DbContext
{
public DbSet<CompanyListId> Contacts { get; set; }
}
}
Controller:
public PartialViewResult SelectCompanyFromDropdown()
{
using (var dc = new CompanyListIdDbContext())
{
var content = from p in db.Companies
select new { p.CoId, p.CompanyName };
}
//I want to set Models ID = to each instance of coid
//Set Models CompanyName to each instance of companyname
return PartialView();
}
I am not sure where to go from here, I am attempting to make a drop down from this model.
I updated my code block to:
public PartialViewResult SelectCompanyFromDropdown()
{
using (var dc = new CompanyListIdDbContext())
{
var content = from p in db.Companies
select new CompanyListId
{
Id = p.CoId,
CompanyName = p.CompanyName
};
return PartialView(content.ToList());//giving an error
}
}
And my view to:
#model Portal.Models.CompanyListId
#Html.DropDownListFor(m => m.CompanyName, Model.CompanyName)
This also doesn't seem to work, I need to return my Model from the action I would think, that way the view can properly use the data.
You should project the result to your class CompanyListId
var content = from p in db.Companies
select new CompanyListId
{
Id = p.CoId,
CompanyName = p.CompanyName
};
EDIT:
I am not sure about the error, but you can try :
public PartialViewResult SelectCompanyFromDropdown()
{
List<CompanyListId> content = null;
using (var dc = new CompanyListIdDbContext())
{
content = (from p in db.Companies
select new CompanyListId
{
Id = p.CoId,
CompanyName = p.CompanyName
}).ToList();
}
return PartialView(content);
}
You can just select a new instance of your class like so:
var content = from p in db.Companies
select new CompanyListId
{
Id = p.CoId,
CompanyName = p.CompanyName
};