Can AppFabric be the session state provider and use local cache? - session-state

I am using AppFabric as the session state provider in my ASP.Net MVC2 app, and I would like it to also use the local cache. I have the following entry in my web.config right after the configSections node:
<dataCacheClient>
<localCache
isEnabled="true"
sync="TimeoutBased"
objectCount="100000"
ttlValue="300" />
<hosts>
<host name="127.0.0.1" cachePort="22233"/>
</hosts>
</dataCacheClient>
I also have the following entry in web.config as a child of the system.web node:
<sessionState mode="Custom" customProvider="AppFabricCacheSessionStoreProvider">
<providers>
<add name="AppFabricCacheSessionStoreProvider" type="Microsoft.ApplicationServer.Caching.DataCacheSessionStoreProvider" cacheName="Default" sharedId="DefaultId"/>
</providers>
</sessionState>
Unfortunately if I add something to session then run the following two commands in the AppFabric powershell, anything I added to my session data is no longer there which leaves me to believe it was not using local cache:
Stop-CacheCluster
Start-CacheCluster
I also try caching objects with AppFabric using the following code and after I start and stop the CacheCluster the once cached object is no longer cached:
var factory = new DataCacheFactory();
var cache = factory.GetCache("Default");
cache.Put("Key", "Test");
However if I instantiate AppFabric using the following code where I explicitly tell it to use local cache rather than relying on the web.config entry it works:
var servers = new List<DataCacheServerEndpoint>(1) { new DataCacheServerEndpoint("127.0.0.1", 22233) };
var configuration = new DataCacheFactoryConfiguration {
Servers = servers,
LocalCacheProperties = new DataCacheLocalCacheProperties(100000, new TimeSpan(0, 30, 0), DataCacheLocalCacheInvalidationPolicy.TimeoutBased)
};
var factory = new DataCacheFactory(configuration);
var cache factory.GetCache("StpWebSession");
cache.Put("Key", "Test");
What am I doing wrong, why doesn't my web.config entry work in telling AppFabric to use local cache? Can you use AppFabric as your session state provider and also have it use local cache?

I found a little ditty at http://social.msdn.microsoft.com/Forums/en-US/velocity/thread/24e72dab-bb20-47ec-aae2-77423b1d296b.
Basically, "enableSessionState" is "true" by default meaning you need to go remote for all requests. If you set the property to "ReadOnly" the session state object will be retrieved from the Local Cache. Then if local cache is invalidated it will go to remote store again.

Related

Service Fabric - Are Endpoint definitions required for service remoting?

I'm trying to understand in what scenarios endpoint definitions are required in the ServiceManifest. I have a stateful service with the multiple service remoting listeners defined. My implementation of CreateServiceReplicaListeners:
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
{
return new[]
{
new ServiceReplicaListener(context => this.CreateServiceRemotingListener(context)),
new ServiceReplicaListener(context =>
{
return new FabricTransportServiceRemotingListener(context,
new CustomService<string>(),
new FabricTransportRemotingListenerSettings
{
EndpointResourceName = "ustdfdomgfasdf"
});
}, name: "CustomListener")
};
}
The endpoint resource name for the custom listener is garbage. I have not defined that endpoint in the service manifest's resources:
<Resources>
<Endpoints>
<Endpoint Name="ServiceEndpoint" />
<Endpoint Name="ReplicatorEndpoint" />
</Endpoints>
</Resources>
However, in testing I find I'm still able to get a proxy to CustomListener:
InventoryItem i = new InventoryItem(description, price, number, reorderThreshold, max);
var applicationInstance = FabricRuntime.GetActivationContext().ApplicationName.Replace("fabric:/", String.Empty);
var inventoryServiceUri = new Uri("fabric:/" + applicationInstance + "/" + InventoryServiceName);
//Doesn't fail
ICustomService customServiceClient = ServiceProxy.Create<ICustomService>(inventoryServiceUri,
i.Id.GetPartitionKey(),
listenerName: "CustomListener");
//Still doesn't fail
var added = await customServiceClient.Add(1, 2);
To me, this indicates endpoint definitions aren't required for service remoting as long as the endpoint and listener names are unique. Is that so? If not, why does my example work?
Endpoints are required to tell service fabric to allocate ports in the node for the services being started on that node, this will prevent port collision when many services are opening ports in the node.
Once allocated, these are create as Environment Variables in the service process, something like: Fabric_Endpoint_<EndpointName> : port
When you create the Listeners, they are responsible to open the ports, generally using the ports allocated via Endpoints, but not prevents you creating a custom listener to Open any port (If running with enough privilege to do so)
CreateServiceRemotingListener(context) creates the default listeners
EndpointResourceName setting tell which endpoint to be used by a listener, if not defined, DefaultEndpointResourceName setting is used as the default Endpoint, the default value is "ServiceEndpoint"
What I am not sure to answer right now is: if EndpointResourceName is not found, it uses DefaultEndpointResourceName, I assume so, need to check the code to confirm that.
When multiple listeners are using the same port, they generally have a path to identify each of them, something like: tcp://127.0.0.1:1234/endpointpath

How to access settings.xml in Azure Service Fabric stateful/stateless service?

How can I access and read parameters definied in PackageRoot/Settings/Settings.xml file from my stateful/stateless service code?
For example I have a section DocumentDbConfig with Parameter EndpointUrl:
<Section Name="DocumentDbConfig">
<Parameter Name="EndpointUrl" Value="{url}"/>
</Section>
And I would like to read it in my code:
public async Task<ServiceActionResult<Result>> GetResult()
{
_client = new Client({{ EndpointUrl }}); //HOW TO GET ENDPOINT URL FROM SETTINGS?
}
As long as your code has access to the ServiceContext you can access all of the configuration packages that were deployed with your service. For example:
serviceContext.CodePackageActivationContext.GetConfigurationPackageObject("Config")
where "Config" is the name of the configuration package. From there, you can access all of the sections and keys/values within each section. Be sure to refer to the ConfigurationPackage documentation as a guide on how to access this data, as well as how to listen to events that fire when the configuration package changes.

Mobile Services (.Net backend) using incorrect connection string

I am struggling to make the .Net backend of Mobile Services use the correct connectionString. When I publish the service I select the correct connection string for "MS_TableConnectionString". If I check the web.config on the server (via FTP) I see what I would expect:
web.config on server:
<connectionStrings>
<add name="MS_TableConnectionString" connectionString="Data Source=tcp:[ServerAddress].database.windows.net,1433;Initial Catalog=[MyMobileService_db];Integrated Security=False;User ID=[correctUserName];Password=[CorrectPassword];Connect Timeout=30;Encrypt=True" providerName="System.Data.SqlClient" />
In my context it is configured to use a connection string called MS_TableConnectionString:
private const string connectionStringName = "Name=MS_TableConnectionString";
public MyMobileServiceContext() : base(connectionStringName)
{
Schema = "MyMobileService";
}
To see what connection string is actually being used I added this to an example controller:
Example Client Code:
public class ExampleController : ApiController
{
MyMobileServiceContext context;
public ApiServices ApiServices { get; set; }
public ExampleController()
{
context = new MyMobileServiceContext();
}
public async Task<IHttpActionResult> PostExample(ExampleItem item)
{
ApiServices.Log.Warn("ConnectionString: " + context.Database.Connection.ConnectionString);
...
}
And when I look at the Log Entry on Mobile Services I see a different UserName and Password:
[2014-04-15T12:26:33.1410580Z] Level=Warn, Kind=Trace, Category='PostExampleItem', Id=00000000-0000-0000-0000-000000000000, Message='ConnectionString: Data Source=[SameServerAddress].database.windows.net;Initial Catalog=[SameDatabaseName];User ID=[DifferentUserName];Password=[DifferentPassword];Asynchronous Processing=True;TrustServerCertificate=False;'
The different username and password are the same as I see in the original .PublishSettings file that I downloaded under the name of SQLServerDBConnectionString but I have no idea where this is stored on the server?
Because of the different username and password I see the following exception in the log:
[2014-04-15T13:18:11.2007511Z] Level=Error, Kind=Trace, Category='App.Request', Id=d7ec6d25-f3b7-4e88-9024-217be40ae77f, Exception=System.Data.Entity.Core.ProviderIncompatibleException: An error occurred accessing the database. This usually means that the connection to the database failed. Check that the connection string is correct and that the appropriate DbContext constructor is being used to specify it or find it in the application's config file. See http://go.microsoft.com/fwlink/?LinkId=386386 for information on DbContext and connections. See the inner exception for details of the failure. ---> System.Data.Entity.Core.ProviderIncompatibleException: The provider did not return a ProviderManifestToken string. ---> System.Data.SqlClient.SqlException: Cannot open database "master" requested by the login. The login failed.
Login failed for user '[DifferentUserName]'.
This session has been assigned a tracing ID of '[GUID]'. Provide this tracing ID to customer support when you need assistance.
Any help would be much appreciated as at the moment I am having to hard code the whole connection string in the constructor of the Context to make it work.
Thanks
F
UPDATE: 15th April 2014 15:23
I deleted all my publisher profiles and created a copy of the original .PublishSettings file. From this I deleted all but one profile. I then deleted the SQLDBConnectionString attribute to confirm that it is not because I was sending this that was causing the problem. The result was no change, it is still using the DifferentUserName and Password so it must be reading it from the server somewhere.
We have a hole at the moment in that we pick up the connection string from the portal yet don't expose the ability to set or modify connection strings there.
The work-around is to set an application setting in the portal and then use that in your code using the ApiServices class, something like this (in your controller)
string connectionString = this.Services.Settings["YourConnectionStringAsAppSetting"];
I know it is confusing... we'll make it easier to access and modify the connection strings.
Henrik

connectionString in Entity Framework

I am stuck. I have spent nearly a day to solve but to no avail.
PROBLEM: Connecting to production database using entity framework.
I connect fine on development.
<add name="DefaultConnectionString" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=MONDO;Integrated Security=True" providerName="System.Data.SqlClient" />
<add name="MONDOEntities" connectionString="metadata=res://*;provider=System.Data.SqlClient;provider connection string="Data Source=.\SQLEXPRESS;Initial Catalog=MONDO;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Moving to production, I used (from the production web.config file) the existing "DefaultConnectionString" parameters (ID and Password) to edit the MONDOEntities connectionString. (can I do this?) Also, I expanded the metadata in MONDOEntities to include .csdl, .ssdl, .msl and I prefixed it with (guessing, again, can I do this?) MONDO. Bold parts are changes from dev web.config to production web.config. *Note, the connectionStrings below were not created by Visual Studio, I just changed some info myself to try and make it work on the production side.
<add connectionString="Data Source=MPOC\SQLEXPRESS;Database=Mondo;User ID=xxx;Password=xxxxx;" name="DefaultConnectionString" />
<add name="MONDOEntities" connectionString="metadata=res://*/MONDO.csdl|res://*/MONDO.ssdl|res://*/MONDO.msl;provider=System.Data.SqlClient;provider connection string="Data Source=MPOC\SQLEXPRESS;persist security info=True;Database=Mondo;User ID=xxx;Password=xxxxx;MultipleActiveResultSets=Tru e;App=EntityFramework"" providerName="System.Data.EntityClient" />
The error message I get is:
Unable to load the specified metadata resource.
Line 62: /// Initializes a new MONDOEntities object using the connection string found in the 'MONDOEntities' section of the application configuration file.
Line 63: /// </summary>
Line 64: public MONDOEntities() :
QUESTION: Can I simply modify the connectionStrings manually or does it need to run through a compilation process? It is a website project so it compiles, on the fly, the first time after I upload to production. It does not get precompiled on my local dev computer. I guess, bottom line, how do I set up a proper connectionString for an entity connection for a database in production?
I'm on a project where I need to learn an existing website. I'm making my first bug fix and having learned ado.net, I created an entity data model and made some code changes. Everything works smooth in development.
I move the files to production and then I get this error:
"The specified default EntityContainer name 'MONDOEntities' could not be found in the mapping and metadata information.
Parameter name: defaultContainerName"
I googled this error message and based on some findings, I expanded my "metadata" shown below. This was more of a shot in dark for me:
ORIGINAL (auto generated in web.config when I created the entity data model):
connectionString="metadata=res://*
NEW (I edited/added this):
connectionString="metadata=res://*/MONDO.csdl|res://*/MONDO.ssdl|res://*/MONDO.msl;
This seemed to get past the first error and I get to a new error message (as posted in OP):
Unable to load the specified metadata resource.
Line 62: /// Initializes a new MONDOEntities object using the connection string found in the 'MONDOEntities' section of the application configuration file.
Line 63: /// </summary>
Line 64: public MONDOEntities() :
I think that there is a problem with my metadata information. However, given that the original, auto generated connectString only contains "metadata=res://*", I really don't know how to go about correcting this. Actually, I'm not even super sure that this is the root of the problem.
Bottom line, my entity model works smooth in dev but isn't connecting in production. Any thoughts are appreciated ... thanks.
The connection string has nothing to do with compilation, as long as you didn't define some transformation to be performed on it or you have some custom hooks that operate on it.
So yeah, you can modify it by hand.
You probably got those metadata wrong, try and play with them (EG removing the prefix).
Also are you absolutely sure that, in your production environment, the right connectionString is being loaded and used by the MONDOEntities?

HTTP BasicAuthentication doesn't immediately realize, when a user's role changes. What can I do about it?

I have deployed a Webservice on JBossAS 5.1 GA. To use HTTP Basic Authentication, The SBC class is annotated the following way:
#Stateless
#SecurityDomain(value = "MyWSSecurity")
#RolesAllowed(value = "WebserviceUser")
#WebContext(contextRoot="/MyWS", urlPattern="/*", authMethod="BASIC", transportGuarantee="NONE", secureWSDLAccess=true)
#WebService(endpointInterface = "MyWS")
public class MyWSImpl implements MyWS {
public String doSomething() {
return "something";
}
}
Generally this works fine. But the following szenario bothers me.
User who is in role WebserviceUser calls the service.
The role Webservice is now taken AWAY from the user.
Problem: He still can call the service.
I guess this happens, because user credentials and roles are stored in HttpSession object on the server side. After server restart the user is denied from calling the service.
What can I do about that?
Regards
EDIT: The problem does not apply only to JBOSSWS EJB3 webservices, but to anything using JAAS authentication.
Found 2 solutions that are appropriate for me.
Solution 1) Change the Default timeout for the JAAS Cache
You can do this by editing $JBOSS_HOME/server/default/conf/jboss-service.conf. Locate the part of the file, where JaasSecurityManager MBean is configured and change the attribute DefaultCacheTimeout to an acceptable small value (60 seconds is fine for me). If you want to disable caching of security credentials entirely, set the value to 0.
<!-- JAAS security manager and realm mapping -->
<mbean code="org.jboss.security.plugins.JaasSecurityManagerService"
<!--
skipped some configuration
-->
<!-- DefaultCacheTimeout: Specifies the default timed cache policy timeout
in seconds.
If you want to disable caching of security credentials, set this to 0 to
force authentication to occur every time. This has no affect if the
AuthenticationCacheJndiName has been changed from the default value.
-->
<attribute name="DefaultCacheTimeout">60</attribute>
<!-- DefaultCacheResolution: Specifies the default timed cache policy
resolution in seconds. This controls the interval at which the cache
current timestamp is updated and should be less than the DefaultCacheTimeout
in order for the timeout to be meaningful. This has no affect if the
AuthenticationCacheJndiName has been changed from the default value.
-->
<attribute name="DefaultCacheResolution">30</attribute>
<!--
skipped some configuration
-->
</mbean>
Solution 2: Call method flushAuthenticationCache("MyWSSecurity") on JaasSecurityManager MBean, whenever a user's role changes.
Regards