How to Migrate from echoBot to Virtual Assistant? - c#

I am trying to migrate the MyBot that I created and run in echoBot to VirtualAssistant.
But there was one problem at the beginning.
There is no "accessor".
I was able to store user information and conversations via an accessor.
How can I store dynamic information without using accessors?
Below is the code I used.
var someQuery = await _accessors.SomeQuery.GetAsync(stepContext.Context, ()=> new SomeQuery(), cancellationToken);
With the stored query information, I was able to use the query variables at will.
I wonder what the virtual assistant can do to replace this.

I found a solution. Now I know I have an IStatePropertyAccessor. I was too hasty. I thought the Accessor had disappeared because there was no Accessor class.

Related

FileHelpers - Creating a field object

I am trying to dynamically add field properties to a record class that I am also building dynamically using FileHelpers.Dynamic.DelimitedClassBuilder. I have no issues creating the class object and I currently add a field using the AddField(String) method.
As my apps grows I now have a need to declare specific field properties in various situations. So in the same sense I wanted to use FileHelpers.Dynamic.DelimitedFieldBuilder to create a field object and then pass that to my DelimitedClassBuilder object using the method AddField(DelimitedFieldBuilder).
However I am unable to instantiate a new object using FileHelpers.Dynamic.DelimitedFieldBuilder. When I issue the following code I get an error stating that DelimitedFieldBuilder does not contain a constructor that takes two arguments.
FileHelpers.Dynamic.DelimitedFieldBuilder fb = new FileHelpers.Dynamic.DelimitedFieldBuilder("ClassName", "Type");
Looking at the documentation it appears that this class does only have properties associated with it, so I am kind of stuck on how to actually implement this. It seems like it should be fairly easy but I cant seem to figure it out. Thanks for any help.
Not familiar with that functionality of file helpers; however, in the vast majority of functions/methods across .NET there is usually a way to assign properties after the class is instantiated.
Try something like this:
FileHelpers.Dynamic.DelimitedFieldBuilder fb = new FileHelpers.Dynamic.DelimitedFieldBuilder();
fb.Whatever = "ClassName";
fb.otherwhatever = "Type";
Just a stab. I have no idea if it will work or not.
The constructors of DelimitedFieldBuilder are internal so you'll run into difficulty with your approach. However AddField(String) returns a DelimitedFieldBuilder, so you might be able to use that.
It might be easier to make your own class MyFieldBuilder which calls the standard AddField(String).

ASP.Net Idenity - Override FindByName to include extra search criteria

We have a setup where clients run stand-alone version of our system, but they all link to the same Identity Database with Entity Framework.
A user can be registered as a user on many versions of the application, thereby having multiple accounts with the same username, but the applicationId (stored in the web.config) is unique.
What I would like to do is use the UserManager.FindByName function, but have it automatically add the "&& applicationId = X" to the request sent to the context.
Well you can inherit from the UserManager class, but you have to rewrite the original code (.NET now is open source you can find the original code) and add your logic to it. However, this may be a lengthy action.
What i suggest is if you are using Entity Framework search for the user id by name and application id, then pass the id for the FindById method.
If follow down the implementation, you'll eventually find this method:
public virtual Task<TUser> FindByIdAsync(TKey userId)
{
this.ThrowIfDisposed();
return this.GetUserAggregateAsync((Expression<Func<TUser, bool>>) (u => u.Id.Equals(userId)));
}
In order to override this properly, it would have to be inside the UserStore class, since there are loads of internal methods (otherwise you'd have to rewrite every single internal method in the class), and add a new Type Parameter that would accept your ApplicationId, since UserStore is a generic class. Then you would be able to write another FindByIdAsync method, because it's a virtual method and it can't be overridden. You would also have to rewrite the GetUserAggregateAsync internal method, because it isn't prepared to handle your new Type Parameter.
Now, there are probably a few more hiccups that would show up, but you can, ultimately, rewrite this method to suit you, but I would advise against it because it's A LOT of work to achieve something that might be possible in another way.
Docs: http://docs.asp.net/projects/api/en/latest/autoapi/Microsoft/AspNet/Identity/EntityFramework/UserStore-TUser-TRole-TContext-TKey/index.html
Code: https://github.com/aspnet/identity/blob/master/src/Microsoft.AspNet.Identity.EntityFramework/UserStore.cs

How do I ignore table storage resource not found exceptions without using table contexts?

In my C# application I am initializing a CloudTable instance via the following code:
var account = CloudStorageAccount.Parse(connectionString);
var client = account.CreateCloudTableClient();
client.DefaultRequestOptions.RetryPolicy = new LinearRetry();
var table = client.GetTableReference(tableName);
table.CreateIfNotExists();
return table;
When I execute an operation to retrieve a record from table storage, I usually do something like:
var realEntity = _table.Value.ExecuteQuery(StreamKeyConfigurationEntity.CreateQuery(calculatedPartitionKey, calculatedRowKey))
.SingleOrDefault();
After this has been in production for a while I noticed some 404 exceptions coming back from this line. After looking around it appears that this is normal behavior when table storage does not have any matching entities, which is annoying.
The good news I came across several articles (like this one that claim that you can get around this by setting an IgnoreResourceNotFoundException property to true.
Perfect, except that it uses a TableContext not a CloudTable. This is an issue becomes intellisense explicitly says to use the Table namespace instead of the context namespace, as the GetTableServiceContext() method is marked as obsolete.
Is there any way to blanket ignore resource not found exceptions so I don't have to wrap all queries in a try/catch using the CloudTable stuff?
Sorry, but it's generally dangerous for the library to just ignore certain exceptions that are returned as per the REST contract of the service. If you have particular requirements and want to ignore exceptions, you should use the build-in language features that enable this (namely, try-catch).

C# NHibernate with Spring LazyInitializationException when using the data

I'm working on an NHibernate project, and where I had trouble loading collections earlier (http://stackoverflow.com/questions/4213506/c-hibernate-criteria-loading-collection), I now have problems using data.
I'm using C# in combination with the NHibernate and Spring.Net framework, and I get an LazyInitializationException after I load for instance an 'ordercredit', and then accessing an object of the ordercredit.
I use this code for getting the OrderCredit:
OrderCredit oc = CreditService.getOrderCredit(ordercredit.Id);
The code I use for loading is done using a DAO implementation:
[Transaction(TransactionPropagation.Required, ReadOnly = true)]
public OrderCredit GetOrderCredit(long ordercreditid)
{
var creditrules = Session.CreateCriteria(typeof(OrderCredit));
creditrules.Add(Restrictions.Eq("Id", ordercreditid));
return creditrules.List<OrderCredit>()[0];
}
When I run this on my local machine, everything works fine, and I actually intended to load a list of those 'ordercredits', but that went wrong as well, so I tried a simpler step first.
The objects within the 'OrderCredit' are defined as [OneToMany].
When I put this on the testserver, and try to access the 'OrderObject' object of the loaded OrderCredit, I get the error:
NHibernate.LazyInitializationException: Initializing[.OrderObject#5496522]-Could not initialize proxy - no Session.
Code that fails:
Log.Debug(oc.OrderObject.Name);
Code that works:
Log.Debug(oc.Id);
This happens for any object that's part of the OrderCredit, but I am able to access the property fields of the OrderCredit (for instance the OrderCredit.Id).
Also, when I access any of the objects BEFORE I return the data to the original function calling the method, then it does cache the information or so, as I can access it then.
I've read a lot about this problem, like turning off Lazy, but that did not work for me either (or I did that on the wrong place).
The thing that frustrates me most, is the fact that it actually does work on my local machine, and not on the testserver. What could I be doing wrong?
Any help is highly appreciated.
1st update:
I am using now a GenericDao, using the default method of loading 1 ordercredit. I use the following code to load 1 ordercredit by Id.
OrderCredit oc = GenericService.Load<OrderCredit>(Id);
The code that's inside the GenericDAO is the following, BUT it does not end or breaks the session, which means I am able to access the objects attached to the ordercredit:
[Transaction(TransactionPropagation.Supports, ReadOnly = true)]
public T Load<T>(long id) where T : ISaveableObject
{
var obj = Session.Load<T>(id);
return obj;
}
This is nearly the same code as I had in the function which I included earlier in this question.
I'm now really confused because I don't know what it could be that ends the session. I will work with it now as it works, but I want to change it later on, so I can use my function to call the entire collection and access them via a for each loop.
Currently, I use my 'getOrderCredits' function to get the list of OrderCredit objects, and in the foreach, I get the Id, and use the GenericDao.Load to get the actual item, and can access the objects and such. Of course this is not the way it should be and needs to be.
I'd be amazed if I get this solved.
This is a common problem people have when using NHibernate. It happens because:
You open a session
You load an entity from the database which references another entity
You close the session
You try to access a property on your referenced entity
NHibernate tries to lazily load the entity from the database using the same session that loaded the parent entity
The session is closed, so NHibernate throws exceptions like woah.
You have a few options here:
Keep your session open longer, preferably using something like the unit of work pattern, which will give you tighter control.
Eagerly load your referenced entities when you query:
In your case as spring is managing your transaction for you the 2nd option is probably the quickest/easiest solution.
var creditrules = Session.CreateCriteria(typeof(OrderCredit));
creditrules.Add(Restrictions.Eq("Id", ordercreditid))
.SetFetchMode("OrderObject", FetchMode.Eager);
This will load the OrderObject when you load the OrderCredit.

C# asp.net custom MembershipUser.createUser() method, call it from createuserwizard control

I have created custom MembershipUser, MembershipProvider and RolePrivoder classes. These all work and I am very happy with it, apart from one thing. I have an extra field in the "Users" table. I have an overridden method for CreateUser() that takes in the extra variable and puts it into the DB.
My issues is that I want to be able to have this called from the Create User Wizard control. I have customized the control to have a drop down to populate my extra field. I have used the following code to store that piece of info but I am at a loss of how I either use the profile or call my custom CreateUser Method:
// Create an empty Profile for the newly created user
ProfileCommon p = (ProfileCommon)ProfileCommon.Create(CreateUserWizard1.UserName, true);
// Populate some Profile properties off of the create user wizard
p.CurrentLevel = Int32.Parse(((DropDownList)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("clevel")).SelectedValue);
// Save profile - must be done since we explicitly created it
p.Save();
Thank you for any and all help
Jon Hawkins
I think your solution is the "easiest" you're going to get. You could create your own wizard and call the correct method, but that's a lot more work.
The only thing I could recommend is using the OnCreatedUser event instead.
reference: 4guysfromrolla
This is not the answer but I found a work around, would still like to know if someone could answer the question directly...
public void UpdateCurrentLvl_OnDeactivate(object sender, EventArgs e)
{
int level = Int32.Parse(((DropDownList)CreateUserWizard1.CreateUserStep.ContentTemplateContainer.FindControl("clevel")).SelectedValue);
MyMembershipUser myUser = (MyMembershipUser)Membership.GetUser(CreateUserWizard1.UserName);
myUser.CurrentLVL = level;
Membership.UpdateUser(myUser);
}
In my first CreateUserWizardStep if put the method above to fire on deactivate. As at this point it has inserted the user into the DB I can get the User out, cast to my MembershipUser class, set the variable and all the update method.
As I say this is a work around from the way I would liked to have solved it but it works.
Thanks
This is also incredibly hacky, but in the past when I've had to do similar things, I've just crammed the extra value into an unused parameter, like the password reset question or answer. Though, I'm not entirely sure how you'd manage this using the wizard.
It's ugly, but as long as it is explicitly documented (to be safe, I'd comment on the method itself as well as anywhere you reference it) it will work fine.
It's also a lot less work than creating your own wizard.

Categories