Caching in a WCF application - c#

The below code throws an error of "Object reference not set to an instance of an object" When calling mycache.Get("products"). Im using a WCF application. Im not 100% im using caching correctly. Any advice?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Caching;
namespace DataLayer {
public class Products
{
public List<Product> Current()
{
Cache mycache = new Cache();
if (mycache.Get("products")== null)
{
using (DataLayer.AccessDataContext db = new AccessDataContext())
{
var products = from p in db.fldt_product_to_supp_parts
where p.Current
select new Product
{
WholesaleCode = p.WholesaleCode,
ProductCode = p.Product_Code
};
mycache["products"] = products.ToList();
}
}
return mycache["products"] as List<Product>;
}
} }
EDIT : I'm using .net 3.5

I'm not sure what is wrong with your code, because I don't know off-hand how Cache is implemented, but a little searching uncovered the following Walkthrough from MSDN:
http://msdn.microsoft.com/en-us/library/dd997362.aspx
Caching Application Data in a WPF Application
And the following link gives an overview:
http://msdn.microsoft.com/en-us/library/dd997357.aspx
In summary, it appears that for .NET v4 onwards, caching has been moved into System.Runtime.Caching from System.Web.Caching.

From the look of the documentation you shouldn't be creating your own instance of the Cache class (it says the constructor is for framework use only). Try using Cache.Get instead?
EDIT (in response to comment)...
From the MSDN docs here:
One instance of this class is created per application domain, and it remains valid as long as the application domain remains active. Information about an instance of this class is available through the Cache property of the HttpContext object or the Cache property of the Page object.
So, it looks like Cache.Get is available when you're within a Page; otherwise you can call HttpContext.Cache to get the active cache. Either way, there's a single Cache object for your entire application and you definitely shouldn't be creating one of your own.

For non ASP.NET applications use caching from System.Runtime.Caching.
Your code throws System.NullReferenceException because internal cache CacheInternal of System.Web.Caching.Cache isn't initialized using internal void SetCacheInternal(CacheInternal cacheInternal) method. It initializes by ASP.NET infrastructure in System.Web.HttpRuntime class.

Unless I'm missing something, you're trying to use the ASP .NET cache within your WCF service. In order for this to work, you need to turn on ASP .NET compatibility using the AspNetCompatibilityRequirementsMode Enumeration. If you're self-hosting you'll have to roll your own.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class CalculatorService : ICalculatorSession
{
}

Related

How to do CRUD in Web Forms using Controller classes from ASP.NET Core?

So at this point, I have two projects in my VS solution:
RecipeAPI, which is a ASP.Net Core Application
RecipeUI, which is a Windows Forms Application
Inside the RecipeAPI project, I already have the model and controller classes made and now I have to create a prototype UI in which the functionality should be implemented.
My issue is using the classes and objects from the API project, into the UI one. For example:
I am trying to populate a ListBox. Inside RecipeAPI, I have a controller class named RecipeController, which has the following method for retrieving data from the database:
[Route("v1/recipe/{recipeBy}")]
[HttpGet()]
public List<Recipe> GetRecipes(string recipeBy)
{
using (var con = _connFactory())
{
con.Open();
return con.Query<Recipe>("SELECT * FROM dbo.Recipe WHERE RecipeBy = #recipeBy", new { recipeBy }).ToList();
}
}
This was tested using PostMan, works perfectly fine. However, I am having huge issues trying to figure out how to populate the ListBox. In fact, I am having issues figuring out how I can use certain methods from a project to another. To be noted that I have already added references.
Moving forward, this is the method in the Forms class which is supposed to populate the ListBox.
private void ShowRecipes(string recipeBy)
{
List<Recipe> recipeList = new List<Recipe>;
recipeList = GetRecipes(recipeBy);
recipeListBox.DataSource = recipeList;
}
I am not entirely sure how correct this is. Basically what I am trying to do is get the list of recipes by calling the method GetRecipes() from RecipeController. Unfortunately, I am getting errors such as:
The type or namespace name 'Recipe' could not be found
The name 'GetRecipes' does not exist in the current context
So what am I missing here? Am I even on the right track or I shouldn't even try combining Web Forms and ASP.Core? And if this works too, then how can I be able to access methods from RecipeAPI.Controllers in RecipeUI Form?
You have to make Api Call to the RecipeAPI project from Windows Forms Application
in order to use the methods/logic of the APIs Project.
This is the way to make an API call:
How to make HTTP POST web request

HttpContext and Caching in .NET Core >= 1.0

I am trying to port some libraries from the old MVC5 System.Web based stack to .Net Core. One issue I am having is the changes in the caching. For example, in MVC5 I was able to read and write i18n related data:
[Code Snippet 1]
public static Dictionary<string, IEnumerable<CoreDictionaryResource>> DictionaryResourcesCache {
get { return (Dictionary<string, IEnumerable<CoreDictionaryResource>>)HttpContext.Current.Cache(string.Concat(_Dictionary, DictionaryID, CultureID)); }
set { HttpContext.Current.Cache(string.Concat(_Dictionary, DictionaryID, CultureID)) = value; }
}
However, I am reliably informed that System.Web and its HttpContext does not contain a Cache field. I can see a Current field and then a whole host of fields within this such as Application and Session but alas no Cache.
I've done the necessary in Startup.cs and the app is configured to use both in memory caching and sessions. I know that the sessions work as I have other POCOs cached using
[Code Snippet 2]
return System.Web.HttpContext.Current.Session.GetObject<User>("AuthenticatedUser");
where GetObject in an extension I created.
Am I barking up the wrong tree trying to use HttpContext to read out from the Cache or perhaps I need to use IDistributedCache as see here, here and on SO.
But really I just to port the method within [Code Snippet 1]...
Any pointer you can give on the new .Net Core with regards to caching would be really helpful.
Just FYI I do not want any logic in Controllers, nor in Views. The application I am building usings separate DLLs for data access and logic so please don't post any examples with DI into the Controllers. This issue is more at an infrastrcture level before it hits the MVC stack.
Thanks guys and gals.
The in memory cache functionality is still there, it has just been moved around a bit. If you add
"Microsoft.Extensions.Caching.Memory": "1.1.0"
to you project.json file and the add
services.AddMemoryCache();
to you Startup.ConfigureServices method, you'll have set up a singleton memory cache instance that works pretty much like the old one did. You get to it via dependency injection so a controller with a constructor can get a instance.
public class HomeController: Controller
{
private IMemoryCache _cache;
public HomeController(IMemoryCache cache)
{
_cache = cache;
}
}
You can then use _cache in the class above to get to the globally available singleton class. There are other sorts of caches that you might want look at as well, including a Redis cache for out of process storage.
You should use the In Memory Cache only as HttpContext cache object was actually appdomain cache object although it is exposed using the HttpContext
From the msdn https://msdn.microsoft.com/en-us/library/system.web.httpcontext.cache(v=vs.110).aspx
There is one instance of the Cache class per application domain. As a result, the Cache object that is returned by the Cache property is the Cache object for all requests in the application domain.
We should use the
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Caching.Memory;
using System;
using Microsoft.Extensions.FileProviders;
namespace CachingQuestion
{
public class Startup
{
static string CACHE_KEY = "CacheKey";
public void ConfigureServices(IServiceCollection services)
{
//enabling the in memory cache
services.AddMemoryCache();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var fileProvider = new PhysicalFileProvider(env.ContentRootPath);
app.Run(async context =>
{
//getting the cache object here
var cache = context.RequestServices.GetService<IMemoryCache>();
var greeting = cache.Get(CACHE_KEY) as string;
});
}
}
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
My answer is focused on how to port caching implementation from old ASP.Net MVC to ASP.Net CORE the easiest and fastest way possible, and also focusing on not rely on dependency injection.
There is a perfect equivalent of ASP.Net MVC's HttpContext.Current.Cache. Its implementation was intended exactly to permit easy porting between frameworks. This is:
System.Runtime.Caching/MemoryCache
This is pretty much the same as the old day's ASP.Net MVC's HttpRuntime.Cache. You can use it on ASP.Net CORE without any dependency injection. This is how to use it:
// First install 'System.Runtime.Caching' (NuGet package)
// Add a using
using System.Runtime.Caching;
// To get a value
var myString = MemoryCache.Default["itemCacheKey"];
// To store a value
MemoryCache.Default["itemCacheKey"] = myString;

Entity Framework Code First in class library

I just started trying my hands on EF4 code first this morning and I created my POCO, data context and Initializer classes in a separate class library, I believe it's the regular boiler plate type code. I reference the class in an MVC3 application and set the initializer in the Global.asax. On running the app, I notice the following problems
1. No database is created anywhere (Then I add an entry in the web.config for a connection string named after the Context class, still no result)
2. When I try to access the initalized values, I get a null error, obviously because there is no data.
Can anyone please help me with pointers on how to get thi thing to work (would be a shame if I spent my entire christmas day learning this and I still can't get it to work :( )
Thanks
p.s. I tried inserting break points and I hit the app initialization method, but it never hits the Seed method in the initializer even though I add a break point there as well!!
Thanks.
Initializer class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using F2AController.Models;
namespace F2AController.DataObjects
{
public class F2AInitializer : DropCreateDatabaseAlways<F2AContext>
{
protected override void Seed(F2AContext context)
{
var countries = new List<Country>
{
new Country(){ CountryName="Germany", Active = true},
new Country(){ CountryName="Britain", Active = true}
};
countries.ForEach(s => context.Countries.Add(s));
context.SaveChanges();
var providers = new List<Providers>()
{
new Providers(){ ProviderName="InfoBip", ContactDetails="Rturo Manovic", Active=true, MessageRates= new List<ProviderRates>(){new ProviderRates(){ CountryId=1, DateCreated=DateTime.Now, DateModified=DateTime.Now, Rate=0.05M, Active=true}}}
};
providers.ForEach(p => context.Providers.Add(p));
context.SaveChanges();
var usermobiles = new List<MobileTerminal>()
{
new MobileTerminal(){ Active= true, Credits=200, DateCreated=DateTime.Now, MSISDN="4477565444865"}
};
usermobiles.ForEach(u => context.MobileTerminals.Add(u));
context.SaveChanges();
}
}
}
Context Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
namespace F2AController.Models
{
public class F2AContext : DbContext
{
public DbSet<Country> Countries;
public DbSet<MobileTerminal> MobileTerminals;
public DbSet<Providers> Providers;
public DbSet<ProviderRates> ProviderRates;
public DbSet<Property> Properties;
public DbSet<ShortMessage> ShortMessages;
public DbSet<UserProperties> UserProperties;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
}
Global.asax App initialization method
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
Database.DefaultConnectionFactory = new SqlConnectionFactory(ConfigurationManager.ConnectionStrings["F2AContext"].ConnectionString);
Database.SetInitializer<F2AContext>(new F2AInitializer());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
Eureka..finally!
While searching for a solution, I came across this post Entity Framework Database.SetInitializer simply not working
Applying the solution suggested there to force my database to create worked at start up like I expected, but then while running the seed code, it threw a null pointer exception. While investigating, I realized that any attempt to reference the DBSet collections from the Context class yielded the same exception. Inspecting further I realised that instead of using
public DbSet<MobileTerminal> MobileTerminals { get; set; }
I had used
public DbSet<MobileTerminal> MobileTerminals;
Which meant that I did not get any implicit object initialization, hence the null pointer exception. I removed the forced initialization code and ran the app again, this time the seed code didn't run until I accessed a page which actually queried the data context and it ran perfectly.
Apparently, due to Lazy loading, the initialization code is not run until it is actually needed, i.e. the first time the data context is queried in the application.
I hope this helps anyone who has the same problem in the future.
I wanted to share another issue when using a class library for code first & stumbled across this post. I had my code first POCO and DataContext classes in a library project too and wanted to use this project to create my code first database. I figured out that there is a -ProjectName flag with which one can specify the class library project to look for when creating the database.
add-migration -Name 'InitialCreate' -ProjectName 'MyProject.Data'
update-database -ProjectName 'MyProject.Data'
The issue might be with the connectionstring you are using in your web.config.
For SQL CE use following
<add name="YourContext"
connectionString="Data Source=|DataDirectory|yourDB.sdf"
providerName="System.Data.SqlServerCe.4.0"/>
For SQL Express use following
<add name="YourContext"
connectionString="Data source=.\SQLEXPRESS;Integrated Security=True;Initial Catalog=YourDatabase;"
providerName="System.Data.SqlClient" />
I guess this should make things work.
Also, I think you should look at this article EF Code First DB Initialization Using Web.Config. It's better to initialize the database from web.config rather than from global.asax file

a proxy type with the name account has been defined by another assembly

We have 2 orgs running in our on-premise crm 2011 system.
We have generated early bound classes for both orgs.
One of our plugins is throwing the "a proxy type with the name account has been defined by another assembly" error when deactivating an account.
That plugin only references one of the early bound dll's.
How do I get the CRM system to respect the namespace of these references.
I've tried the few items that show up from Google and none are working.
Since you can reproduce this with 2 vanilla orgs I would imaging there is something OUTSIDE the code layer we can do without having to go back and refactor a bunch of code for the 2 orgs.
Thanks,
Jon
The problem is actually with WCF attempting to deserialize the server response and not being able to identify the correct type. The best method to sort this issue is to pass in the current assembly using Assembly.GetExecutingAssembly() to the ProxyTypesBehavior() while creating the proxy like so.
using (serviceProxy = new OrganizationServiceProxy(config.OrganizationUri,
config.HomeRealmUri,
config.Credentials,
config.DeviceCredentials))
{
// This statement is required to enable early-bound type support.
serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior(Assembly.GetExecutingAssembly()));
}
You may run into this issue when referencing different assemblies containing proxy-classes, i.e. one assembly wrapping the server SDK (Microsoft.Xrm.Sdk) and another assembly wrapping the client SDK (Microsoft.Xrm.Sdk.Client).
In such a scenario it seems to be required to tell the OrganizationServiceProxy which assembly should be used to resolve the proxy classes.
This should help:
var credentials = new ClientCredentials();
credentials.Windows.ClientCredential = new System.Net.NetworkCredential(userName, password, domain);
var proxy = new OrganizationServiceProxy(new Uri(discoveryUrl), null, credentials, null);
proxy.EnableProxyTypes(typeof(CrmServiceContext).Assembly);
var context = CrmServiceContext(proxy);
The important thing is to call EnableProxyTypes by passing the correct assembly. I saw another solution using CrmConnection but CrmConnection is only available in the client SDK, which means that you can't instantiate a "server-OrganizationServiceProxy" this way. EnableProxyTypes(Assembly assembly) works for both sides.
Hope this helps.
Regards,
MH
It maybe years since this question has been raised. However, I faced this problem recently and have been extremely worried about thousands of lines of code to be changed. However, I was lucky to find the following simple change to get myself out of hell:
Suppose there are two context objects you deal with:
an OrganizationServiceContext object: context1
a CrmSvcUtil Context object: context2
and a single OrganizationServiceProxy object: service
if in a single method, you make multiple CRUD operations using the same service object but with either of context objects as exemplified above, it is highly probable that this error be raised. However, by doing the following, you can prevent it to happen.
Every time you want to work with context1, you precede the context object with the service object as following:
service.EnableProxyTypes(typeof(OrganizationServiceContext).Assembly);
using (var context1 = new OrganizationServiceContext(_service)){
// your classic code here
}
Also, every time you want to work with context2, you follow the same structure:
service.EnableProxyTypes(typeof(HiwebContext).Assembly);
using (var context = new XYZContext(this._service)){
// your CrmSvcUtil none-classic code here
}
this normally means that there is one or more assemblies with the same method name or property to fix this use the fully qualified name of the assembly.. for example in the using System.IO for example if you had a method named the same way in your Class code that conflicts with System.IO.... you would write your fix like
thisObject.System.IO.Path( ---- ) = somthing for example.. does this make sense..?
I found that adding the Assembly.GetExecutingAssembly() solved the problem.
adding the Assembly.GetExecutingAssembly() solve my problem, you also need to add using System.Reflection;
thanks

Class constructor (from C# web service) won't auto-implement properties in C# MVC

I'm running two instances of VS2010 on my local machine. One instance is running my Web Service (written in C#). The other instance is running my MVC web app (also C#). The MVC web app has a reference to the web service. I can successfully invoke web service methods from within the MVC app.
In my web service is a PageNavigation class:
// PageNavigation.cs
using System;
using System.Collections.Generic;
using System.Text;
public class PageNavigation
{
public string Page_Number { get; set; }
public string Page_Count { get; set; }
public PageNavigation()
{
Page_Number = "1";
Page_Count = "2";
}
}
By default, this should return an object with auto-implemented properties when I call the class constructor:
WebService.PageNavigation pageNavigation = new WebService.PageNavigation();
This works when constructing a PageNavigation object elsewhere in the web service.
pageNavigation.Page_Number
"1"
pageNavigation.Page_Count
"2"
However, running the same line of code on the MVC isn't giving the same result; the object's properties are all null values.
pageNavigation.Page_Number
null
pageNavigation.Page_Count
null
Is this the expected behavior? Is there a way to populate the properties with default values as intended? If more information is needed please let me know and I will update the question.
The service reference only sees the schema of your object, not business logic; in your case, your service reference just created a shell data type in the MVC application. When you create a service reference, it's actually creating another type with the same property names and types as the type defined in the service.
For your particular scenario (simply providing default property values and not more general business logic), you should be able to apply the [System.ComponentModel.DefaultValue] attribute to your properties in order for the class generator to recognize that these properties should be populated with a default value.
Incidentally, if the service reference were reusing existing types (if you had this type in a common library that was referenced both by the service and the application, for example), then your business logic would be intact.
An alternative would be to implement a factory pattern, whereby you call a function on the web service that instantiates (and optionally populates) the data object, then returns it to the client.
Yes, this is expected behaviour. The MVC site is not actually using your PageNavigation class. It is a simple copy (generated when you add the web service reference) containing of all the properties, but none of the methods, including the constructor.
You could work around this by refactoring your service so the entities are in a separate assembly and then you can reuse this assembly on the client as an option when you generate the proxy.
If you insist on using the same types between client and service, then on the "Advanced" tab of the "Add Service Reference" dialog, you can choose to reuse the types in your server assembly.
I would move that class out of the service and into a class library project referenced by the service and by the client.
And I wouldn't do this for such a small reason as default values. this violates SOA by coupling the service and the client. It will obviously not work for clients which are not running .NET.
What serializer are you using to deserialize the response from the server? Some of them (like the DataContractSerializer for example) do not call the default constructor.
The solution that you should use if you are in fact using DataContractSerializer is to use the OnDeserialized attribute like this:
using System.Runtime.Serialization;
public class PageNavigation
{
public string Page_Number { get; set; }
public string Page_Count { get; set; }
public PageNavigation()
{
Init();
}
[OnDeserialize]
void Init()
{
Page_Number = "1";
Page_Count = "2";
}
}

Categories