I am trying to add an autoincrement to a simple model via an IDocumentStoreListener. I have found that the documentation regarding implementation of this feature is fairly sparse (any pointers would be greatly appreciated). I have been trying to follow this blog post but it appears to be out of date. When i try to implement
store = new EmbeddableDocumentStore
{
RunInMemory = true
}
.RegisterListener(new AuditableEntityListener(() => "Test User"))
.Initialize();
I get a build error stating "Cannot convert lambda expression to type Raven.Client.IDocumentStore because it is not a delegate type".
I managed to get it to build by using this code
store = new EmbeddableDocumentStore
{
RunInMemory = true
}
.RegisterListener(new AuditableEntityListener(store ))
.Initialize();
The code for the listener is as follows
public class PublicIdStoreListener : IDocumentStoreListener
{
HiLoKeyGenerator generator;
IDocumentStore store;
public PublicIdStoreListener(IDocumentStore store)
{
this.store = store;
generator = new HiLoKeyGenerator(store, "verifications", 1024);
}
public void AfterStore(string key, object entityInstance, RavenJObject metadata)
{
throw new NotImplementedException();
}
public bool BeforeStore(string key, object entityInstance, RavenJObject metadata)
{
var verification = entityInstance as VerifyAccountModel;
if (verification.PublicId == "0")
{
verification.PublicId = generator.GenerateDocumentKey(store.Conventions, entityInstance);
}
return false;
}
}
However, when i run the application it hits the PublicIdStoreListener when any document is stored, not just the VerifyAccountModel, which causes the application to throw an exception.
I was wondering if anyone can point me in the right direction on this as I am confused as to how this is actually supposed to be implemented. Thanks in advance.
EDIT
I updated the documentlistener to the following
public bool BeforeStore(string key, object entityInstance, RavenJObject metadata)
{
if (entityInstance.GetType() == new VerifyAccountModel().GetType())
{
var verification = entityInstance as VerifyAccountModel;
if (verification.PublicId == "0")
{
verification.PublicId = generator.GenerateDocumentKey(store.Conventions, entityInstance);
}
}
return true;
}
UPDATE
I figured out that i cant attach the store via RegisterListener in the same line that it is instantiated. It has to be done afterwards otherwise the store is still null when passed in. Thank you for your help.
I am not sure if there's a way to register the listener to only fire for certain types, but you can certainly structure your code to only process VerifyAccountModel entities.
var verification = entityInstance as VerifyAccountModel;
if (verification == null)
return false; // We can't do anything, just let it pass through
Also, my understanding is that you should return true when you make a change, false if no change was made. This determines whether the entity needs to be re-serialized. If that is correct, the whole thing might be restructured as follows.
var verification = entityInstance as VerifyAccountModel;
if (verification != null && verification.PublicId == "0")
{
verification.PublicId = generator.GenerateDocumentKey(store.Conventions, entityInstance);
return true; // change made, re-serialize
}
return false; // no change made
Related
I have the following table
Permissions Table
On login, I am getting the values of ProductEdit, ProductView, ProductDelete for that logged in user and storing them in session to be used later for custom authorization on some actions within the project. This is achived with the following code (note var permissionJoin)
if (usr != null)
{
Session["OperatorId"] = usr.OperatorId.ToString();
Session["Username"] = usr.Username.ToString();
Session["GroupId"] = usr.GroupId.ToString();
var permissionsJoin = from up in db.UserPermissions
join op in db.Operators
on up.GroupId equals usr.GroupId
select new UserPermissionData
{ UserGroupId = up.GroupId, P_Edit = up.ProductEdit, P_Create = up.ProductCreate, P_Delete = up.ProductDelete };
Session["ProductPermission"] = permissionsJoin.ToList<UserPermissionData>();
return RedirectToAction("LoggedIn");
}
I am using a named class [UserPermissionData - that has the four properties I need] to store these values. The results are getting stored in the session fine.
Now onto my authorization class were I need to extract those values and check - if the user has the permission for a particular. I have the following code
public class AuthorizeProductEdit : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//lets get the session values of the current user's permissions
var userP = (UserPermissionData)HttpContext.Current.Session["ProductPermission"];
var editProduct = userP.P_Edit;
if (editProduct.ToString() == "Y")
{
return true;
}
else
{
return false;
}
}
}
at the point of clicking an edit action for the logged in user I am getting an "Unable to cast object of type" error [see image]
Error Image
How can I cast back that query to be able to use if for checking my permissions.
You store in Session is a List<UserPermissionData> so you must cast session value to List<UserPermissionData>
var userP = HttpContext.Current.Session["ProductPermission"] as List<UserPermissionData>;
if (userP == null) return false;
return userP.Any(x => x.P_Edit.ToString() == "Y");
I am updating a library that uses Autofac so that, in addition to the original configuration file (registered via Autofac), it can optionally take a function to accomplish that same goal (again, registered via Autofac). The original is something like this:
public MyClass(ConfigFile config = null)
{
this._activatorLoader = a => {
// old config code here...
}
}
The updated version I'd like is:
public MyClass(
Func<Input, IList<Activator>> activatorLoader = null,
ConfigFile config = null)
{
if (activatorLoader != null)
{
this._activatorLoader = activatorLoader;
}
else
{
this._activatorLoader = a => {
// old config code here...
}
}
}
The problem is that Autofac is seeing my request for a list of something and always providing the function. I tried switching to a delegate and get the same problem:
public delegate IList<Activator> ActivatorLoader(Input input);
public MyClass(
ActivatorLoader activatorLoader = null,
ConfigFile config = null)
{
if (activatorLoader != null)
{
this._activatorLoader = activatorLoader;
}
else
{
this._activatorLoader = a => {
// old config code here...
}
}
}
The loading of the activators must still be delayed, I'd like the flexibility of registering any function based on the situation, and old code (without an activator loader registered) should still work. Is there any way to prevent Autofac from autogenerating the Func?
The class will be instantiated through dependency injection in another class. At a later time, the activator loading code will be triggered (if needed).
var myObject = conatiner.Resolve<MyClass>();
// time passes...
myObject.DoActivatorLoading();
The primary goal is to prevent Autofac from creating the Func<Input, IList<Activator>> if it is not explicitly set. Is this possible?
Perhaps, it will be easier to create a separate class for activator loading ?
public class ActivatorsLoader
{
public IList<Activator> Load(Input input)
{
///
}
}
///
public Class(
ActivatorsLoader activatorsLoader = null,
ConfigFile config = null)
{
///
}
But it would be good to see the use cases of your Class.
I am in the early stages of developing a new module.
Much of it is laid out in terms of the models etc. Also have the migrations all set up and my database now has the tables for my module.
I am encountering the following error when calling ContentManager.New<myPart> and would like some help please.
Error is this:
An unhandled exception has occurred and the request was terminated. Please refresh the page. If the error persists, go back
Specified cast is not valid.
System.InvalidCastException: Specified cast is not valid.
at Orchard.ContentManagement.ContentCreateExtensions.New[T]
(IContentManager manager, String contentType)
The chunk of code that fires the exception is this:
public static T New<T>(this IContentManager manager, string contentType) where T : class, IContent {
var contentItem = manager.New(contentType);
if (contentItem == null)
return null;
var part = contentItem.Get<T>();
if (part == null)
throw new InvalidCastException();
return part;
}
Here are the various parts to my module that are related to the operation i am struggling with:
ContentPart
public class GoogleMapsSettingsPart : ContentPart<GoogleMapsSettingsPartRecord>
{
public string ApiKey {
get { return Record.ApiKey; }
set { Record.ApiKey = value; }
}
}
ContentPartRecord
public class GoogleMapsSettingsPartRecord : ContentPartRecord
{
public virtual string ApiKey { get; set; }
}
Handler
public GoogleMapsSettingsPartHandler(IRepository<GoogleMapsSettingsPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
Migration for this table
// Settings Table
SchemaBuilder.CreateTable("GoogleMapsSettingsPartRecord", table => table
.ContentPartRecord()
.Column("ApiKey", DbType.String, c => c.WithLength(60))
);
Some of the code from the controller for this model etc
public AdminController(IContentManager contentManager, IShapeFactory shapeFactory, IServiceLocatorService serviceLocatorService, INotifier notifier)
{
_contentManager = contentManager;
_serviceLocatorService = serviceLocatorService;
_notifier = notifier;
Shape = shapeFactory;
T = NullLocalizer.Instance;
}
/// <summary>
/// Display Settings
/// </summary>
/// <returns></returns>
public ActionResult Settings()
{
var settings = _serviceLocatorService.GoogleMapsSettings;
var editor = CreateSettingsEditor(settings);
var model = _services.ContentManager.BuildEditor(settings);
return View((object)model);
}
Finally - the Services where my call throws this exception
private GoogleMapsSettingsPart _settings;
public GoogleMapsSettingsPart GoogleMapsSettings
{
get {
if (_settings == null)
{
_settings = _contentManager.Query<GoogleMapsSettingsPart, GoogleMapsSettingsPartRecord>().List().FirstOrDefault();
if (_settings == null)
{
_settings = _contentManager.New<GoogleMapsSettingsPart>("GoogleMapsSettings");
}
}
return _settings;
}
}
The actual line where the exception happens is _settings = _contentManager.New<GoogleMapsSettingsPart>("GoogleMapsSettings");
I have tried all sorts of stuff in place of "GoogleMapsSettings" though nothing is working.
I'm pretty sure at this point it's something simple, though it's avoiding me..My limited knowledge of Orchard is stumping me
Any help would be appreciated :)
The exception is thrown because your content type does not have the part you specified to get.
_contentManager.New<GoogleMapsSettingsPart>("GoogleMapsSettings");
This method call creates a new content item of type GoogleMapSettings and gets the content item as a GoogleMapsSettingsPart. However, it seems that GoogleMapSettings content type does not have a GoogleMapsSettingsPart. That's why the exception gets thrown here.
var part = contentItem.Get<T>();
if (part == null)
throw new InvalidCastException();
You must either attach the part dynamically to your content type or do it in a migration (or manually in the admin, but that's not a good idea). Your migration should look like this.
this.ContentDefinitionManager.AlterTypeDefinition("GoogleMapsSettings",
alt => alt
.WithPart("GoogleMapsSettingsPart");
Ok, so I fixed it...
My understanding of how Orchard works is still very much in the learning stages.
for this particular operation I didn't want to have a content type in the admin - though not sure why after adding the ContentType it still didn't work...
anyway, adding the lines below to my handler took care of the rest. I believe it's actually creating a temporary type so one isn't needed in the system.
public GoogleMapsSettingsPartHandler(IRepository<GoogleMapsSettingsPartRecord> repository)
{
Filters.Add(new ActivatingFilter<GoogleMapsSettingsPart>("GoogleMapsSettings"));
Filters.Add(StorageFilter.For(repository));
Filters.Add(new TemplateFilterForRecord<GoogleMapsSettingsPartRecord>("GoogleMapsSettings", "Parts/GoogleMapsSettings"));
}
I'v got the same error, but in my case it was everything ok with migration class.
The reason was unlucky merge, which deleted my driver class of my part.
Just look at this code of Activating method of ContentPartDriverCoordinator class. In my case there was no partInfo for my content part and resulted part became ContentPart, so casting throws an exception
var partInfos = _drivers.SelectMany(cpp => cpp.GetPartInfo()).ToList();
foreach (var typePartDefinition in contentTypeDefinition.Parts) {
var partName = typePartDefinition.PartDefinition.Name;
var partInfo = partInfos.FirstOrDefault(pi => pi.PartName == partName);
var part = partInfo != null
? partInfo.Factory(typePartDefinition)
: new ContentPart { TypePartDefinition = typePartDefinition };
context.Builder.Weld(part);
}
I have an entity instance created using the metadata coming from the server:
breeze.NamingConvention.camelCase.setAsDefault();
...
var applicationType = metadataStore.getEntityType('Application');
var application = applicationType.createEntity();
None of the objects in this particular model has circular dependencies.
After the user has made some changes to the corresponding object, I need to perform some custom validation on that entity, so I need to convert that object back to its JSON simple form and send it back to a validation Controller (ASP.NET MVC4).
The question is how to transform the entity to JSON such that:
The resulting object reflects the naming conventions used in the server side.
The object contains simple properties and not knockout observables.
And does not contain any other additional property or function used internally by breeze.
I was expecting to find something like:
var json = application.toJS();
But such method does not exist. Using ko.toJS(application) also doesn't work because (1), (2) and (3) are not fulfilled.
I'm sure this should be trivially easy to do, but I just can't find anything even remotely related on the documentation.
UPDATE: You'll forgive me for the horrible hack, but because I'm in a hurry what I did that temporarily solved my problem was just exposing the unwrapEntities internal function of entityManager. I also changed the function definition a little bit (just to exclude that annoying entityAspect):
function unwrapEntities(entities, metadataStore, includeEntityAspect) {
var rawEntities = entities.map(function(e) {
var rawEntity = unwrapInstance(e);
if (includeEntityAspect !== undefined && includeEntityAspect === false) {
return rawEntity;
}
...
});
}
And because I have the entityManager available at all times in my services, I was able to extend my types definition to do something like the following:
function createApplicant(initialValues) {
var applicant = applicantType.createEntity(initialValues);
applicant.toJS = function () {
var unwrappedEntities = entityManager.unwrapEntities([applicant], entityManager.metadataStore, false);
return unwrappedEntities[0];
};
return applicant;
}
And that's precisely what I need:
var json = application.toJS();
This is a good idea! Could you please add it to the Breeze User Voice. It makes a lot of sense to expose the "unwrapping" of a Breeze entity.
Just a small side note, the unwrap "hack" that you wrote may not work in a future version of Breeze because we are currently in process of refactoring some of this code, but I will try to expose a "cleaner" version as part of the Breeze api.
This may be outdated solution but I did some hack in my typescript class to do this without help from the breeze core.
I did this hack since my breeze version and typing file did not include the unwrap method and I did not want to upgrade it just now.
Another benefit is that the result class is absolutely clean of any extra properties not included in the metadata as well as you can control if you want just the plain entity or if you want the related entities embedded in the result as well.
Just include this code in your typescript class to get this done:
public unwrapEntity(entity: breeze.Entity, includeRefs: boolean): any {
var refs = [];
return this.unwrapEntityInner(entity, refs, includeRefs);
}
private objInArray(obj: any, refs: Array<any>): boolean {
var ret = false;
for (var i = 0; i < refs.length; i++) {
if (obj === refs[i]) {
ret = true;
break;
}
}
if (!ret)
refs.push(obj);
return ret;
}
private unwrapEntityInner(entity: breeze.Entity, refs: Array<any>, includeRefs: boolean): any {
var data = {};
for (var prop in entity) {
if (entity.hasOwnProperty(prop) && ko.isObservable(entity[prop])) {
data[prop] = entity[prop]();
if (typeof data[prop] !== 'undefined' && data[prop] != null) {
if (typeof data[prop].entityAspect !== 'undefined') {
data[prop] = (includeRefs && !this.objInArray(data[prop], refs)) ? this.unwrapEntityInner(data[prop], refs, includeRefs ) : null;
}
else if ($.isArray(data[prop])) {
if (!includeRefs || this.objInArray(data[prop], refs))
data[prop] = [];
else {
var tmp = data[prop];
data[prop] = [];
for (var i = 0; i < tmp.length; i++) {
data[prop].push(this.unwrapEntityInner(tmp[i], refs, includeRefs));
}
}
}
}
}
}
return data;
}
I am looking for a more better way to update a record using Entity Framework.
Below is what I am using now, where playerFromModel is data fetched from View.
public bool UpdatePlayer(PlayerEntity playerFromModel)
{
bool updateSuccessfull = false;
using (var context = new PlayerEntities())
{
var player = context.Player.Where(m => m.emailAddress == playerFromModel.EmailAddress).FirstOrDefault();
if (player != null)
{
player.emailAddress = playerFromModel.EmailAddress;
player.first_name = playerFromModel.FirstName;
player.last_name = playerFromModel.LastName;
player.alt_email_id1 = playerFromModel.AlternateEmailAddress;
player.street = playerFromModel.Street;
player.city = playerFromModel.City;
player.state = playerFromModel.State;
player.zip = playerFromModel.Zip;
player.country_code = playerFromModel.CountryCode;
player.phone1 = playerFromModel.Phone;
try
{
context.SaveChanges();
updateSuccessfull = true;
}
catch
{
updateSuccessfull = false;
}
}
}
return updateSuccessfull;
}
As you can see I have to manually map each of the fields and the same approach I have followed everywhere.
I was thinking that there definitely has to be a better way to do this.
Please guide me on this. Thanks.
You can just use TryUpdateModel. e.g.
bool updateSuccessfull = false;
using (var context = new PlayerEntities())
{
var player = context.Player.Where(m => m.emailAddress == playerFromModel.EmailAddress).FirstOrDefault();
if (player != null)
{
//Beware this will try to map anything it can. This can be dangerous
if(TryUpdateModel(player)){
try
{
context.SaveChanges();
updateSuccessfull = true;
}
catch
{
updateSuccessfull = false;
}
}
}
}
return updateSuccessfull;
}
I wouldn't though see here Real example of TryUpdateModel, ASP .NET MVC 3.
You could use Automapper or something similar as MiBu said. Create a ViewModel link is here of the Player and then map from that to the entity
//Get a PlayerUpdate ViewModel
using (var context = new PlayerEntities())
{
// fetch the domain model that we want to update - BTW I'd use a repository pattern but that is another debate
var player = context.Player.Where(m => m.emailAddress == playerFromModel.EmailAddress).FirstOrDefault();
if (player != null)
{
// Use AutoMapper to update only the properties of this domain model
// that are also part of the view model and leave the other properties unchanged
AutoMapper.Map<UpdatePlayerViewModel , PlayerEntity>(viewModel, player);
try
{
context.SaveChanges();
updateSuccessfull = true;
}
catch
{
updateSuccessfull = false;
}
}
However I am of the opinion that updating entity properties is a significant thing and shouldn't be done automatically. Others feel the same. Jimmy Bogard who created AutoMapper doesn't seem to believe it needs two way mapping (However he says that is partly as they built AutoMapper for their requirement) Similar answer here on Stackoverflow saying do it yourself.
It depends on the complexity of your application but I would look at using the command pattern to send a message to an appropriate handler containing your properties and have the handler update them. If it was successful we do one thing if it wasn't we do another. Same pattern is described in MVC in Action. See similar (here is the link)[http://www.paulstovell.com/clean-aspnet-mvc-controllers] and here is the second link