"Lambda Parameter not in scope" exception using SimpleRepository's Single method - subsonic

I'm attempting to use the SimpleRepository to perform a fetch based on a non-ID property. Here's the Customer class I'm using:
[Serializable]
public class Customer : IEntity<Guid>
{
public Guid ProviderUserKey { get; set; }
public Guid ID
{
get; set;
}
}
I'm using SimpleRepository with migrations turned on. The code that throws the "Lambda Parameter not in scope" is below:
public class CustomerRepository :
ICustomerRepository
{
private readonly IRepository _impl;
public CustomerRepository(string connectionStringName)
{
_impl = new SimpleRepository(connectionStringName,
SimpleRepositoryOptions.RunMigrations);
}
public Customer GetCustomer(string userName)
{
var user = Membership.GetUser(userName);
// Code to guard against a missing user would go here
// This line throws the exception
var customer = _impl.Single<Customer>(c => c.ProviderUserKey.Equals(user.ProviderUserKey));
// Code to create a new customer based on the
// ASP.NET Membership user would go here
return customer;
}
}
I'm not sure at what point in the LINQ expression compilation this throws, but I am running this example on an empty database. The schema generations gets far enough to create the table structure, but can't evaluate the expression.
Does anyone know what I might be doing wrong?
Thanks!

I've had reports of this - can you add this (and your code) as an issue please?

Related

(ServiceStack) Location of business logic in a message based architecture

What is the best practice for placing business logic in message based design?
Im using servicestack for building my api.
The wiki shows the example of placing the RequiredRole Attribute on the message instead of the service handling it.
In a sense this [RequiredRole]/[Authenticate] is business logic/security attached to the message.
Concrete example
Say for example i would add DeleteAddress message:
public class DeleteAddress : IReturn<bool>
{
public int AddressId { get; set; }
}
But for this to be properly secure i want to check either Admin Role, permission to ManageAllAddresses or that the AddressId is linked to this user (maybe in session, maybe through a db call).
How would i best go about this?
Proposition
Is the following code the good practice and if so how would i implement it?
[RequiredRole("Admin")]
[RequiredPermission("ManageAllAddresses ")]
[RequiredAddressLinkedToAccount]
public class DeleteAddress : IReturn<bool>
{
public int AddressId { get; set; }
}
ServiceStack's recommendation is to keep your ServiceModel free of dependencies so we'd recommend to annotate your Service implementation classes instead which you can annotate either on the Service class to apply to all Operations or on the individual methods to apply just to that operation, e.g:
[RequiredRole("Admin")]
public class AddressServices : Service
{
[RequiredPermission("ManageAllAddresses ")]
[RequiredAddressLinkedToAccount]
public object Any(DeleteAddress request)
{
}
}
Please note ServiceStack requires your Services to return reference types, which is typically a Response DTO but can also be a string, e.g:
public class DeleteAddress : IReturn<string>
{
public int AddressId { get; set; }
}
To finish of this question. I could make a request filter and add it on the service.
Either inherit from AuthenticateAttribute or Directly from RequestFilterAttribute.
public class RequiredAddressLinkedToAccount : AuthenticateAttribute
{
public RequiredRoleAttribute(ApplyTo applyTo)
{
this.ApplyTo = applyTo;
this.Priority = (int)RequestFilterPriority.RequiredRole;
}
public override void Execute(IRequest req, IResponse res, object requestDto)
{
var dto = requestDto as ILinkedToAccount;
var session = req.GetSession();
if(dto.AccountId == session.Id)
return; //we dont want anything to be blocked if the account Id is there.
//Implement like RequireRoleAttribute
if (DoHtmlRedirectIfConfigured(req, res))
return;
res.StatusCode = (int)HttpStatusCode.Forbidden;
res.StatusDescription = "Address does not belong to you";
res.EndRequest();
}
}

Understanding Asp.Net Identity key points

I am an Asp.net developer but very much new to the Asp.net Identity framework. I have been studying the sample application and followed some tutorials too on Identity but still I am not able to grasp the concept completely. I have very firm grip over Asp.net membership but Identity seems nothing like membership. I will explain what I have done so far.
I am creating a simple application in which I am following code first approach. I have created entity model for User which inherits from IdentityUser and has some extra fields. Below is entity model for User.
public class User : IdentityUser
{
public int? CompanyID { get; set; }
public bool? CanWork { get; set; }
public bool? CanSearch { get; set; }
public Company Company { get; set; }
}
Now in the examples people use the name ApplicationUser but for my own purpose I have used name User. Also there is a method in User or ApplicationUser model which is,
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager)
{
CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
I am unable to understand the purpose of this method. Also from an example I have used the following model for Role,
public class Role : IdentityRole
{
public Role()
{
}
public Role(string roleName, string description)
: base(roleName)
{
this.Description = description;
}
public string Description { get; set; }
}
I understand that an extra field is added but I am unable to understand the purpose of overloaded constructor.
The above mentioned confusions are secondary. My primary confusion is that I am familiar that when I create entity models I use DbSet and DbContext and when I call any entity framework method to access the database, the database is created/drop created whichever scheme I am following.
In Identity which method is responsible for creating the Identity tables in the database? I have a IdentityConfig file in which I declare ApplicationUserManager and ApplicationSignInManager. I have also a Startup file. Previously I had only one Startup file in the App_Start folder and when I run the application and tried to accessed any Identity methods it gave me error and was not creating database. I then made the class as partial and created another partial class with same name at the root and then the exception was gone and tables were created. So Startup class is responsible for creating Identity tables? There are extra columns created automatically in the AspNetUsers like PhoneNumber, PhoneNumberConfirmed, TwoFactorEnabled. I don't need these extra columns. Can I remove these? Can I change the names of the Identity tables that are created?
I know these are very basic questions and not one question at all but if I was unable to find some basic tutorial or example for beginners then it would be very beneficial. What I have found are describing those things which I don't need or making me confuse. I want to understand and have control how Identity should work in my application but till now it seems to me that neither I am grasping it completely and nor being able to make is adjustable to my needs. Its like tutorials and example are teaching me how to make sentences but I am unable to understand the alphabets. :(
First of all you have to define the model - as you're doing - implementing the right interfaces.
Let's say you want to create a user for your application:
public class MyUser : IdentityUser<string, MyUserLogin, MyUserRole, MyUserClaim>
{
public string CompanyName { get; set; }
}
As you can see I've implemented the IdentityUser interface (namespace Microsoft.AspNet.Identity.EntityFramework).
I've specified what type of identifier I want to use for my primary key (string) and included my custom objects to manges login, roles and claims.
Now we can defined the role object:
public class MyRole : IdentityRole<string, MyUserRole>
{
}
Again there's a type and the class I've defined for the management of users belonging to to a role.
public class MyUserRole : IdentityUserRole<string>
{
}
MyUserLogin is going to implement IdentityUserLogin<string>.
MyUserClaim is going to implement IdentityUserClaim<string>.
As you can see each interface need a type for the primary key.
The second step is to create the user store:
public class MyUserStore: UserStore<MyUser, MyRole, string, MyUserLogin, MyUserRole, MyUserClaim>
{
public MyUserStore(MyContext context)
: base(context)
{
}
}
Again we have defined what user, role, login etc etc we want to use.
We need UserStore cause our UserManager is going to need one.
If you're planning to manage roles and associate roles with each user you have to create your RoleStore definition.
public class MyRoleStore : RoleStore<MyRole, string, MyUserRole>
{
public DaufRoleStore(ApplicationDatabaseContext context) : base(context)
{
}
}
Now you can create your UserManager. The UserManager is the real responsible of saving changes to the UserStore.
public class ApplicationUserManager : UserManager<MyUser, string>
{
public ApplicationUserManager(IUserStore<MyUser, string> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new MyUserStore(context.Get<MyContext>()));
manager.UserValidator = new UserValidator<MyUser, string>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
manager.PasswordValidator = new PasswordValidator()
{
RequiredLength = 5,
RequireNonLetterOrDigit = false, // true
// RequireDigit = true,
RequireLowercase = false,
RequireUppercase = false,
};
return (manager);
}
}
This class has a static method which will create a new UserManager for you.
Interesting to note that you can include some validation rules you might need to validate password etc etc.
Last thing is to create or database context.
public class MyContext : IdentityDbContext<MyUser, MyRole, string, MyUserLogin, MyUserRole, MyUserClaim>
{
public MyContext(): base("<your connection string here>")
{
}
public static MyContext Create()
{
return new MyContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<MyUser>()
.ToTable("Users");
modelBuilder.Entity<MyRole>()
.ToTable("Roles");
modelBuilder.Entity<MyUserRole>()
.ToTable("UserRoles");
modelBuilder.Entity<MyUserClaim>()
.ToTable("UserClaims");
modelBuilder.Entity<MyUserLogin>()
.ToTable("UserLogins");
}
}
As you can see I've used the model builder to change the names all the tables.
You can define keys or fields type or tables relations here.
This is the place where you're going to attach your custom classes you want to manage in your context:
public DbSet<MyCustomer> Customers{ get; set; }
Again MyContext has a Create method which returns a new context:
public static MyContext Create()
{
return new MyContext();
}
Now you should have a startup class where you're going to bootstrap your stuff:
[assembly: OwinStartup(typeof(ASPNETIdentity2.Startup))]
namespace ASPNETIdentity2
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.CreatePerOwinContext(MyContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
}
}
}
Here you're going to create your database context and your user manager you can use in your application.
Notice the first line:
[assembly: OwinStartup(typeof(ASPNETIdentity2.Startup))]
This is needed cause you're telling your environment that is the startup class which needs to be called at ... startup.
Now in your controllers you can simply refer to your UserManager doing something like this:
HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
How can you create your tables?
In Visual Studio go to TOOLS -> NuGet Packager Manager -> Package Manager Console.
In the window there's a combobox "Default Project". Choose your ASP.NET MVC project.
Run this command:
Enable-Migrations
It will create a file Configuration.cs in a new folder called Migrations.
If you want to create your database you need to open that file and change the AutomaticMigrationsEnabled to true:
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
Again, from Package Manager Console, you can run:
Update-Database
and all your tables will appear in your database. Don't forget your connection string.
You can download this github project to see how everything works.
You can check these two answers with some other info.
The first of the two has got some links to a blog where you can learn all these things.
NOTE:
You have to do all this if you want to customized every single bit of your environment.

How to save User reference in own Record

What I'm trying to achieve here is to save the current user instance in my ApiConfigurationRecord table. I already dig around the internet, and most of the example is using UserPartRecord. But the troble I encounter is to get the UserPartRecord object itself.
This is my Entity class look like:
public class ApiConfigurationRecord
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual UserPartRecord RegisterBy { get; set; }
}
This is my Migration.cs code look like:
public int Create()
{
SchemaBuilder.CreateTable("ApiConfigurationRecord", table => table
.Column<int>("Id", column => column.PrimaryKey().Identity())
.Column<int>("RegisterBy_id")
.Column<string>("Name", column => column.NotNull())
);
return 1;
}
This is my Action Controller codes:
public ActionResult Test()
{
var userId = this._orchardServices.WorkContext.CurrentUser.Id;
// below code got error: The non-generic method IContentManager.Query() cannot be used with type arguments
this._orchardServices.ContentManager.Query<UserPart, UserPartRecord>().Where(u => u.Id == userId);
return null;
}
For hours I stuck in this problem. Need to know how to save this User relationship object, and most importantly, get the object itself. Please guide me.
Or you could just do
_orchardServices.WorkContext.CurrentUser.As<UserPart>().Record;
Though you will probably want to check user is not null there too. And as Bertrand Le Roy says, you will also need
using Orchard.ContentManagement;
to make use of the .As extension method.
My super-powers tell me that you are missing the following on top of your controller file:
using Orchard.ContentManagement;
The generic version of the Query method is an extension method that is in this namespace.

How update an entity inside Aggregate

I have an aggregate named Campaigns every with a root entity named campaign, this root entity has a list of attempts (entity)
public class Attempts: IEntity<Attempts>
{
private int id;
public AttempNumber AttemptNumber {get;}
//other fields
}
public class Campaign: IEntity<Campaign> //root
{
private int id;
public IList<Attempt> {get;}
//other fields
}
Im using a method to add a campaign attempt
public virtual void AssignAttempts(Attempts att)
{
Validate.NotNull(att, "attemps are required for assignment");
this.attempts.add(att);
}
Problem comes when i try to edit a specific item in attempts list. I get Attempt by AttempNumber and pass it to editAttempt method but i dont know how to set the attempt without deleting whole list and recreate it again
public virtual void EditAttempts(Attempts att)
{
Validate.NotNull(att, "attemps are required for assignment");
}
Any help will be appreciated!
Thanks,
Pedro de la Cruz
First, I think there may be a slight problem with your domain model. It seems to me like 'Campaign' should be an aggregate root entity having a collection of 'Attempt' value objects (or entities). There is no 'Campaigns' aggregate unless you have a parent concept to a campaign which would contain a collection of campaigns. Also, there is no 'Attempts' entity. Instead a collection of 'Attempt' entities or values on the 'Campaign' entity. 'Attempt' may be an entity if it has identity outside of a 'Campaign', otherwise it is a value object. The code could be something like this:
class Campaign {
public string Id { get; set; }
public ICollection<Attempt> Attempts { get; private set; }
public Attempt GetAttempt(string id) {
return this.Attempts.FirstOrDefault(x => x.Number == id);
}
}
class Attempt {
public string Number { get; set; }
public string Attribute1 { get; set; }
}
If you retrieve an Attempt from the Campaign entity and then change some of the properties, you should not have to insert it back into the campaign entity, it is already there. This is how the code would look if you were using NHibernate (similar for other ORMs):
var campaign = this.Session.Get<Campaign>("some-id");
var attempt = campaign.GetAttempt("some-attempt-id");
attempt.Attribute1 = "some new value";
this.Session.Flush(); // will commit changes made to Attempt
You don't need an Edit method. Your code can modify the Attempts in-place, like so:
Attempt toModify = MyRepository.GetAttemptById(id);
toModify.Counter++;
toModify.Location = "Paris";
MyRepository.SaveChanges(); // to actually persist to the DB
Of course how you name the SaveChanges() is up to you, this is the way Entity Framework names its general Save method.

AutoMapper Problem - List won't Map

I have the following class:
public class Account
{
public int AccountID { get; set; }
public Enterprise Enterprise { get; set; }
public List<User> UserList { get; set; }
}
And I have the following method fragment:
Entities.Account accountDto = new Entities.Account();
DAL.Entities.Account account;
Mapper.CreateMap<DAL.Entities.Account, Entities.Account>();
Mapper.CreateMap<DAL.Entities.User, Entities.User>();
account = DAL.Account.GetByPrimaryKey(this.Database, primaryKey, withChildren);
Mapper.Map(account,accountDto);
return accountDto;
When the method is called, the Account class gets mapped correctly but the list of users in the Account class does not (it is NULL). There are four User entities in the List that should get mapped. Could someone tell me what might be wrong?
Try not passing in the accountDto, and let AutoMapper create it for you. When you map to an existing destination object, AutoMapper makes a few assumptions, that you won't have any already-null destination collections for one. Instead, do:
var accountDto = Mapper.Map<DAL.Entities.Account, Entities.Account>(account);
The last thing you should check is that your configuration is valid, so you can try:
Mapper.AssertConfigurationIsValid();
After those CreateMap calls. This checks to make sure everything lines up properly on the destination type side of things.

Resources