i have a web api 2 project the client will request some data that is in a xml format. That XML will never change and i am wondering how i could keep it in ram so that it doesnt deserialize the xml each time it needs data from that file.
Would deserializing it at launch and then keep it in a static variable be the best way as it will only be use for reading ?
[HttpPost]
[Route("api/dosomething")]
public string DoSomething() {
var myData = XmlSerializer(MyDataStruct).Deserialize(something);
return myDate;
}
Here the xml is only used to communicate values to clients. How can i make it so that i could deserialize it once and then return that directly. Would using static member enable this feature ?
A simple cache-aside approach with a static field could be a fair option:
private static MyDataStruct _myData;
[HttpPost]
[Route("api/dosomething")]
public string DoSomething() {
if(_myData == null)
{
_myData = new XmlSerializer(typeof(MyDataStruct)).Deserialize(something);
}
return _myData;
}
If you want even better performance and completely skip both the deserialization from your XML and the serialization of your response body into JSON/XML, then I strongly suggest you an HTTP output caching approach, using a library like this one: AspNetWebApi-OutputCache.
Related
I have a WebApi service that calculates a price of a customized product. The controller function is:
public double Get([FromUri]Specifications specifications)
Specifications is a class that allows to customize the product:
public class Specifications
{
public string Currency;
public int DesktopLicenses;
public Product Product;
public int Licenses;
}
Now, how can I consume this service from C#. I want to avoid to codify manually the URI query with all Specifications variables, I would like to able to use directly an instance of Specificationsto call the service.
If the service is a POST, I could do it doing:
Specifications product = new Specifications( ...);
HttpResponseMessage reponse = httpClient.PostAsJsonAsync("api/pricecalculator", product).Result;
but I cannot find the way to do the same when I use GET.
The example is showing that the GET is passing it a complex object in the call. Normally, that's just a simple request, and returning the complex object -- that's the "best practice". If you need to request something by giving it a complex object - it should still be a POST call. I know the pundits like to think POST/PUT as your change/add for the REST world -- but in the end, frankly there's zero difference between a POST and a GET besides the request body. If you need to give the server complex data, use the request body (aka POST). If it's a simple request -- /api/listofvendors/zone1 - then use a GET.
Web API Get Method with Complex Object as Parameter
example:
[HttpGet]
[Route("~/services/mrf/{mrfnumber}")] // GET specific MRF
public Mrf GetMrfRecord(string mrfnumber) {
using (var ddc = new MRFDataContext(ConnectionString)) {
var options = new DataLoadOptions();
options.LoadWith((Mrf c) => c.MRFParts); //immediate load related MRFParts
ddc.LoadOptions = options;
var mrf = (from u in ddc.Mrfs
where u.MrfNum == mrfnumber
select u).FirstOrDefault();
return mrf ?? null;
}
}
I am using Silverlight with WCF RIA Services.
There is a class in my entity model called Activation. It has properties: Code1 and Code2 along with other properties.
On my silverlight client I need to send an Activation to the server where it picks out values from objects associated with it and populates the Code1 and Code1 attributes. E.g:
Public Sub ServerMethod(ByRef myActivation as Activation)
Dim x as Integer = myActivation.Licence.NumberOfDays
Dim y as Integer = myActivation.Product.ProductSeed
myActivation.Code1 = GetCode1(x,y)
myActivation.Code2 = GetCode2(x,y)
End Sub
Note that the activation codes are not persisted to the database, they simply go back to the client where the user can decide to save if they like from there.
What is the best way to achieve this using WCF RIA Services? At first I thought a named update in the domain service might do the job but there seems to be no Async callback for that.
Any ideas would be greatly appreciated!
It's exactly what the InvokeAttribute is meant for, just put it on your "ServerMethod". About the Async, every single call in wcf ria services is asynchronous and you have to supply a callback to the method if you want to be notified.
EDIT:
I didn't see in your question that you need to pass "Association" properties along the wire. In that case a NamedUpdate, though semantically incorrect, could be easier. Just remember that your context has to be "clean" or you'll submit unintended changes to the server (remember that you have to call the SubmitChanges on the DomainContext).
In case you prefer to use the InvokeAttribute, (and this is the way I'd go) then, yes, as you pointed out, return the "updated" entity to the client and to workaround the problem with the association, use Serialization on your own, i.e ,Serialize your entity and send it to the server, than Deserialize server side and serialize it again before return it to the client, where you'll finally deserialize it.
I'm attaching a piece of code that I use both server and client side that I use with this purpose.
public static class Serialization
{
public static string Serialize<T>(T obj)
{
//Create a stream to serialize the object to.
var ms = new MemoryStream();
// Serializer the User object to the stream.
var ser = new DataContractSerializer(typeof (T));
ser.WriteObject(ms, obj);
byte[] array = ms.ToArray();
ms.Close();
return Encoding.UTF8.GetString(array, 0, array.Length);
}
public static T Deserialize<T>(string obj) where T : class
{
if (obj == null)
return null;
var serializer = new DataContractSerializer(typeof (T));
var stream = new MemoryStream(Encoding.UTF8.GetBytes(obj));
var result = serializer.ReadObject(stream) as T;
return result;
}
}
HTH
I created a Web-API and i would like to get all routes with parameters BeginAddress (string), EndAddress(string), BegineDate (Datetime). I created a new Class SearchRoute with these properties.
I can do a normal Getwith an id or a string but how to do a Get by giving an object? Is this possible?
Would it be possible to do a post/put with an object and than ask for a return?
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync(url + userid);
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
List<Route> list = await SerializeService.Deserialize<List<Route>>(content);
return list;
}
return null;
}
Web API Function
public List<Route> GetAllByCity(SearchRoute sr)
{
return RouteDAO.GetAllByCity(sr);
}
Update:
If i do this, the Post doesn't work but if i create a new controller it works.
[HttpPost]
// POST api/route
public void Post([FromBody]Route route)
{
RouteDAO.Create(route);
}
// POST api/route
[HttpPost]
public List<Route> Post([FromBody]SearchRoute sr)
{
return RouteDAO.GetAllByCity(sr);
}
I prefer sticking with GET even when using a complex object as a parameter. If you are concerned about the length of the URI then remember that:
Prefixing the property names for simple like complex objects is not necessary because the Web API object binding can auto resolve based on property names alone.
The maximum allowed URL length is 2083 characters which is more than sufficient in most cases.
If you we take your example
public class SearchRoute {
public string BeginAddress {get;set;}
public string EndAddress {get;set;}
public DateTime BeginDate {get;set;}
}
[HttpGet]
public List<Route> Get([FromUri]SearchRoute sr)
{
return RouteDAO.GetAllByCity(sr);
}
Uri when searching on
BeginAddress = "Some beginning";
EndAddress = "Some ending"
BeginDate = "2016-01-01T16:40:00"
Resulting query string:
?BeginAddress=Some beginning&EndAddress=Some ending&BeginDate=2016-01-01T16:40:00
Again, the properties will auto resolve even without the object prefix/qualifier and populate the object instance.
Add a domain info to the URL maybe another 50 or so characters
Add a controller name maybe another 30 or so characters
Add the query string = 82 characters
Note that I am not taking into account resolving the special characters like spaces to Url escaped character sequence
Total ≈ 162 characters give or take
Not bad considering that the maximum allowed URL length is 2083 characters, so you have used up only 7% of what is possible in this simple example.
This would probably be the preferred way of doing it because it conforms to the RESTful API standard where GET calls/verbs do not alter data and POST calls/verbs do.
You can pass an object by using a complex type in the URI. You need to help Web API by using the correctly formatted Query String. This would be an example:
?SearchRoute.BeginAddress=TheAddressValue&SearchRoute.EndAddress=TheAddressValue
However, if your Query String starts to become too big, you might be modeling the interaction incorrectly.
Then, in the server you should let Web API know that it should look in the URI for the values:
public List<Route> GetAllByCity([FromUri]SearchRoute sr)
{
return RouteDAO.GetAllByCity(sr);
}
EDIT: I rephrased the question, and it was solved on this post: How do I search within a collection of type ConfigurationSection?
Original Question:
I am storing a list of config options in my web config. I may have 50 or 100 items in here eventually.
I am using the method described here:
http://net.tutsplus.com/tutorials/asp-net/how-to-add-custom-configuration-settings-for-your-asp-net-application/
The good news:
It works, and I have a _Config collection that has all the
The problem: How do I query _Config for a specific feed? (I will have 50-100, maybe more over time.... someday this will move to a db, but not now, as it is hosted on azure, and I need to avoid azure persistence for now.)
(And since this will execute a lot, perhaps it should be hashtable or dictionary? but I don't know how to create em...)
I have struggled, and have been unable to cast _Config into a list or something that I can query.
The question is: How do I get _Config (from the link above) into something that I can query for a specific feed?
The ultimate goal is to have a func that is called to work with a specific feed, and so it needs the config info just from that feed record. In pseudocode, the goal is something like:
getFeed(feedname)
if (_Config.name == feedname) // e.g. feedname is one of the "name" elements in the web.config
// do the stuff
GetData(_Config.feedname.url)
else
// requested feed is not in our config
// tell use can't do it
Or, (also pseudo code)
getFeed(feedname)
try
thisPassFeed = _Config.feedname;
string url = thisPassFeed.url;
// do the stuff
GetData(url);
catch
// requested feed is not in our config
// tell use can't do it
return("can't find that feedname in web.config")
You could create a static class that has a private Dictionary member. In the static constructor access the _Config and do
public static class Feeds
{
private static readonly Dictionary<string, FeedElement> feeds;
static Feeds()
{
feeds = new Dictionary<string, FeedElement>();
var config = ConfigurationManager.GetSection("feedRetriever") as FeedRetrieverSection;
foreach (FeedElement feed in config.Feeds)
{
feeds.Add(feed.Name, feed);
}
}
static public FeedElement GetFeed(string name)
{
return feeds[name];
}
}
Maybe this is dreaming, but is it possible to create an attribute that caches the output of a function (say, in HttpRuntime.Cache) and returns the value from the cache instead of actually executing the function when the parameters to the function are the same?
When I say function, I'm talking about any function, whether it fetches data from a DB, whether it adds two integers, or whether it spits out the content of a file. Any function.
Your best bet is Postsharp. I have no idea if they have what you need, but that's certainly worth checking. By the way, make sure to publish the answer here if you find one.
EDIT: also, googling "postsharp caching" gives some links, like this one: Caching with C#, AOP and PostSharp
UPDATE: I recently stumbled upon this article: Introducing Attribute Based Caching. It describes a postsharp-based library on http://cache.codeplex.com/ if you are still looking for a solution.
I have just the same problem - I have multiply expensive methods in my app and it is necessary for me to cache those results. Some time ago I just copy-pasted similar code but then I decided to factor this logic out of my domain.
This is how I did it before:
static List<News> _topNews = null;
static DateTime _topNewsLastUpdateTime = DateTime.MinValue;
const int CacheTime = 5; // In minutes
public IList<News> GetTopNews()
{
if (_topNewsLastUpdateTime.AddMinutes(CacheTime) < DateTime.Now)
{
_topNews = GetList(TopNewsCount);
}
return _topNews;
}
And that is how I can write it now:
public IList<News> GetTopNews()
{
return Cacher.GetFromCache(() => GetList(TopNewsCount));
}
Cacher - is a simple helper class, here it is:
public static class Cacher
{
const int CacheTime = 5; // In minutes
static Dictionary<long, CacheItem> _cachedResults = new Dictionary<long, CacheItem>();
public static T GetFromCache<T>(Func<T> action)
{
long code = action.GetHashCode();
if (!_cachedResults.ContainsKey(code))
{
lock (_cachedResults)
{
if (!_cachedResults.ContainsKey(code))
{
_cachedResults.Add(code, new CacheItem { LastUpdateTime = DateTime.MinValue });
}
}
}
CacheItem item = _cachedResults[code];
if (item.LastUpdateTime.AddMinutes(CacheTime) >= DateTime.Now)
{
return (T)item.Result;
}
T result = action();
_cachedResults[code] = new CacheItem
{
LastUpdateTime = DateTime.Now,
Result = result
};
return result;
}
}
class CacheItem
{
public DateTime LastUpdateTime { get; set; }
public object Result { get; set; }
}
A few words about Cacher. You might notice that I don't use Monitor.Enter() ( lock(...) ) while computing results. It's because copying CacheItem pointer ( return (T)_cachedResults[code].Result; line) is thread safe operation - it is performed by only one stroke. Also it is ok if more than one thread will change this pointer at the same time - they all will be valid.
You could add a dictionary to your class using a comma separated string including the function name as the key, and the result as the value. Then when your functions can check the dictionary for the existence of that value. Save the dictionary in the cache so that it exists for all users.
PostSharp is your one stop shop for this if you want to create a [Cache] attribute (or similar) that you can stick on any method anywhere. Previously when I used PostSharp I could never get past how slow it made my builds (this was back in 2007ish, so this might not be relevant anymore).
An alternate solution is to look into using Render.Partial with ASP.NET MVC in combination with OutputCaching. This is a great solution for serving html for widgets / page regions.
Another solution that would be with MVC would be to implement your [Cache] attribute as an ActionFilterAttribute. This would allow you to take a controller method and tag it to be cached. It would only work for controller methods since the AOP magic only can occur with the ActionFilterAttributes during the MVC pipeline.
Implementing AOP through ActionFilterAttribute has evolved to be the goto solution for my shop.
AFAIK, frankly, no.
But this would be quite an undertaking to implement within the framework in order for it to work generically for everybody in all circumstances, anyway - you could, however, tailor something quite sufficient to needs by simply (where simplicity is relative to needs, obviously) using abstraction, inheritance and the existing ASP.NET Cache.
If you don't need attribute configuration but accept code configuration, maybe MbCache is what you're looking for?