Comments (7)
Any news on this?
This would be very handy. We are are adding simple objects (that we cannot change as from another project) into temp data and getting the error: Type is not marked as Serializable
Json.Net's JsonConvert.SerializeObject() method would serialise these without the need to add the serializable attribute.
This issue has currently stopped us being able to use the cookieTempData
from cookietempdata.
Feel free to make a PR with this enhancement.
from cookietempdata.
I've also run into the Serializable
requirement and the size issue is also significant. I've done some tests to different types of serialization options: https://github.com/luisgoncalves/CookieTempData/tree/serialization-tests.
Some quick results for that test data (10000 iterations):
- BinarySerializeWithCompression (currently used): Individual size: 577, Total time: 00:00:01.2223728
- BsonSerializeWithCompression (using JSON.NET): Individual size: 313, Total time: 00:00:00.8249299
- BsonSerializeWithoutCompression (using JSON.NET): Individual size: 513, Total time: 00:00:00.1688722
- JsonSerializeWithCompression (JavascriptSerializer): Individual size: 170, Total time: 00:00:00.6050056
- JsonSerializeWithoutCompression (JavascriptSerializer): Individual size: 228, Total time: 00:00:00.1703267
The code with JavascriptSerializer
is already on the project's source; just needs a tweak.
Using JSON.NET is no better than the JavascriptSerializer and the latter avoids the extra dependency. In addition, it doesn't required the [Serializable]
attribute. Finally, compression could probably be removed since the difference is not very big, with the corresponding small performance improvement.
The sample data on the tests is rather basic in terms of types, but I guess real uses cases aren't much different.
What do you think? The changes are minimal.
from cookietempdata.
Feel free to submit a PR if your numbers support smaller size and better perf.
from cookietempdata.
Well, testing deserialization shows that JavaScriptSerializer
may not work. It doesn't seem to have a way to write type information and since we're deserializing into a "object" dictionary, it fails on later casts.
I'll try to submit a PR based on JSON.NET.
from cookietempdata.
I'll reopen if/when PR is submitted.
from cookietempdata.
In case someone wants to do the PR that changes the provider to JSON.NET, here's the code:
/// <summary>
/// A provider for TempData that stores data on cookies.
/// Based on https://github.com/brockallen/CookieTempData
/// Changes:
/// - Use Json.Net BsonSerializer
/// - Do not compress
/// </summary>
public class CookieTempDataProvider : ITempDataProvider
{
const string AnonymousCookieValuePrefix = "_";
const string AuthenticatedCookieValuePrefix = ".";
const string CookieName = "tmp";
const string MachineKeyPurpose = "CookieTempDataProvider:{0}";
const string Anonymous = "<anonymous>";
public static event EventHandler<Exception> ValidationException;
private readonly JsonSerializer jsonSerializer;
public CookieTempDataProvider()
{
this.jsonSerializer = new JsonSerializer();
this.jsonSerializer.Formatting = Formatting.None;
this.jsonSerializer.NullValueHandling = NullValueHandling.Ignore;
this.jsonSerializer.TypeNameHandling = TypeNameHandling.Auto;
}
public void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
byte[] bytes = SerializeWithJsonNetBson(values);
//bytes = Compress(bytes);
var value = Protect(bytes, controllerContext.HttpContext);
IssueCookie(controllerContext, value);
}
public IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
{
var value = GetCookieValue(controllerContext);
var bytes = Unprotect(value, controllerContext.HttpContext);
if (bytes == null && value != null)
{
// failure, so remove cookie
IssueCookie(controllerContext, null);
return null;
}
else
{
//bytes = Decompress(bytes);
return DeserializeWithJsonNetBson(bytes);
}
}
private string GetCookieValue(ControllerContext controllerContext)
{
if (controllerContext.HttpContext.Request.Cookies.AllKeys.Contains(CookieName))
{
HttpCookie c = controllerContext.HttpContext.Request.Cookies[CookieName];
if (c != null)
{
return c.Value;
}
}
return null;
}
private void IssueCookie(ControllerContext controllerContext, string value)
{
// if we don't have a value and there's no prior cookie then exit
if (value == null && !controllerContext.HttpContext.Request.Cookies.AllKeys.Contains(CookieName)) return;
HttpCookie c = new HttpCookie(CookieName, value)
{
// don't allow javascript access to the cookie
HttpOnly = true,
// set the path so other apps on the same server don't see the cookie
Path = controllerContext.HttpContext.Request.ApplicationPath,
// ideally we're always going over SSL, but be flexible for non-SSL apps
Secure = controllerContext.HttpContext.Request.IsSecureConnection
};
if (value == null)
{
// if we have no data then issue an expired cookie to clear the cookie
c.Expires = DateTime.Now.AddMonths(-1);
}
controllerContext.HttpContext.Response.Cookies.Add(c);
}
private string GetAnonMachineKeyPurpose()
{
return String.Format(MachineKeyPurpose, Anonymous);
}
private string GetMachineKeyPurpose(HttpContextBase ctx)
{
if (ctx.User == null || ctx.User.Identity == null || !ctx.User.Identity.IsAuthenticated) return GetAnonMachineKeyPurpose();
return String.Format(MachineKeyPurpose, ctx.User.Identity == null ? "" : ctx.User.Identity.Name);
}
private string GetMachineKeyPurposeFromPrefix(string prefix, HttpContextBase ctx)
{
if (prefix == AnonymousCookieValuePrefix)
{
return GetAnonMachineKeyPurpose();
}
if (prefix == AuthenticatedCookieValuePrefix && ctx.User.Identity.IsAuthenticated)
{
return String.Format(MachineKeyPurpose, ctx.User.Identity.Name);
}
return null;
}
private string GetMachineKeyPrefix(HttpContextBase ctx)
{
if (ctx.User == null || ctx.User.Identity == null) return AnonymousCookieValuePrefix;
return (ctx.User.Identity.IsAuthenticated) ?
AuthenticatedCookieValuePrefix :
AnonymousCookieValuePrefix;
}
private string Protect(byte[] data, HttpContextBase ctx)
{
if (data == null || data.Length == 0) return null;
var purpose = GetMachineKeyPurpose(ctx);
var value = MachineKey.Protect(data, purpose);
var prefix = GetMachineKeyPrefix(ctx);
return prefix + Convert.ToBase64String(value);
}
private byte[] Unprotect(string value, HttpContextBase ctx)
{
if (String.IsNullOrWhiteSpace(value)) return null;
var prefix = value[0].ToString();
var purpose = GetMachineKeyPurposeFromPrefix(prefix, ctx);
if (purpose == null) return null;
value = value.Substring(1);
var bytes = Convert.FromBase64String(value);
try
{
return MachineKey.Unprotect(bytes, purpose);
}
catch (CryptographicException ex)
{
if (ValidationException != null)
{
ValidationException(this, ex);
}
return null;
}
}
private byte[] SerializeWithJsonNetBson(IDictionary<string, object> data)
{
if (data == null || data.Keys.Count == 0) return null;
var ms = new MemoryStream();
using (var writer = new BsonWriter(ms))
{
this.jsonSerializer.Serialize(writer, data);
}
return ms.ToArray();
}
private IDictionary<string, object> DeserializeWithJsonNetBson(byte[] data)
{
if (data == null || data.Length == 0) return null;
var ms = new MemoryStream(data);
using (var reader = new BsonReader(ms))
{
return this.jsonSerializer.Deserialize<IDictionary<string, object>>(reader);
}
}
}
from cookietempdata.
Related Issues (15)
- Circular references.. HOT 2
- Problem with Model State HOT 5
- Problem With CookieTempData HOT 6
- Handle the case when an app tries to store so many data tha a cookie size isn't enough for it HOT 2
- Error occurred during a cryptographic operation. HOT 23
- TempData on SignOut HOT 3
- Error occurred during a cryptographic operation HOT 4
- Public CookieTempDataControllerFactory HOT 8
- The SessionStateTempDataProvider class requires session state to be enabled : Error on production server HOT 1
- 'Invalid length for a Base-64 char array or string.' when using cookie tempdata provider HOT 3
- Move dependencies to NuGet packages HOT 8
- Cookie limits problematic for validation HOT 5
- Transient CryptographicException in LoginExternal HOT 1
- test
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cookietempdata.