ASP.NET MVC Web API 4 REST Webservice: PUT/POST - ing a List of objects - rest

Wondering if its possible and/or supported to put/post an entire object to REST Webservice, as opposed to just some name/value pairs ?
If so, can a List of objects be put/post-ed as well ?
I figured it may be possible, since a GET request is able to return a List of objects, I'd like to do the "reverse" operation with the updated objects (and not send them one at a time, or worse, in individual pieces via name/value pairs) ?
I understand this is a very basic question, but the approach I've taken so far was to just try and code the PUT and get it working (which works if the PUT function has no arguments, like:
public class AObjectController : ApiController
{
public List<int[]> Put()
{
List<int[]> ret = new List<int[]>();
ret.Add(new int[] {-1, 1111});
ret.Add(new int[] {-2, 2222});
return ret;
}
If I specify a single object, or list of objects, I get exceptions:
public List<int[]> Put(AObject object) **CASE 1**
public List<int[]> Put(List<AObject> objects) **CASE 2**
{
List<int[]> ret = new List<int[]>();
ret.Add(new int[] { -1, 1111 });
ret.Add(new int[] { -2, 2222 });
return ret;
}
CASE 1: public List(int[]) Put(AObject object)
CASE 2: public List(int[]) Put(List(AObject) objects)
Heres the code on the client side that is making the call:
public int writeAll(List<T> data)
{
_sendBuffer =
JsonConvert.SerializeObject(
tabletData,
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
);
byte[] b = StringHelper.GetBytes(_sendBuffer);
string url = ContructUrlRequest(null, null);
WebRequest request = WebRequest.Create(url);
request.Method = "PUT";
request.ContentType = "application/json";
request.ContentLength = b.Length;
request.Credentials = CredentialCache.DefaultCredentials;
((HttpWebRequest)request).UserAgent = "...";
//((HttpWebRequest)request).AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(b, 0, b.Length);
requestStream.Flush();
requestStream.Close();
}
WebResponse response = request.GetResponse();
if (response == null)
{
return -1;
}
StreamReader sr = new StreamReader(response.GetResponseStream()); ;
_recieveBuffer = sr.ReadToEnd();
List<int[]> _resultData = JsonConvert.DeserializeObject<List<int[]>>(
_recieveBuffer,
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
);
return data.Count;
}
Thank you.

Used the serialization write code from server on my client side and it worked
public int writeAll(List<AObject> aObjects)
{
string url = ContructUrlRequest(null, null);
WebRequest request = WebRequest.Create(url);
request.Method = WebRequestMethods.Http.Put;
request.ContentType = "application/json; charset=utf-8";
request.Credentials = CredentialCache.DefaultCredentials;
((HttpWebRequest)request).UserAgent = "going insane";
JsonSerializerSettings serializerSettings = new JsonSerializerSettings();
serializerSettings.TypeNameHandling = TypeNameHandling.Objects | TypeNameHandling.Arrays;
serializerSettings.Converters.Add(new IsoDateTimeConverter());
JsonSerializer serializer = JsonSerializer.Create(serializerSettings);
using (Stream requestStream = request.GetRequestStream())
{
using (StreamWriter streamWriter = new StreamWriter(requestStream, new UTF8Encoding(false, true)))
{
using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter))
{
serializer.Serialize(jsonTextWriter, aObjects);
}
}
}
WebResponse response = request.GetResponse();
if (response == null)
{
Log.Info(FIDB.TAG_WSBUFFER, "WSBuffer.writeAll: response = NULL");
return -1;
}
StreamReader sr = new StreamReader(response.GetResponseStream());
_recieveBuffer = sr.ReadToEnd();
_resultData = JsonConvert.DeserializeObject<List<int[]>>(
_recieveBuffer,
new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }
);
return tabletData.Count;
}

Related

Error while reading body of request message through JSON

I need to read content of message from the request body in WCF REST service like -
SERVICE SIDE CODE
string request = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody<byte[]>());
But I am getting an error on the service side, no matter what I try:
Expecting element 'base64Binary' from namespace 'http://schemas.microsoft.com/2003/10/Serialization/'.. Encountered 'Element' with name 'Human', namespace 'http://numans.hr-xml.org/2007-04-15'.
and the service contract is defined as:
//[OperationContract(Name = "LoadMessages", IsOneWay = true)]
[WebInvoke(Method = "POST",
UriTemplate = "/LoadMessages",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
[Description("Inbound Message")]
void LoadMessages();
and the implementation is as:
public void LoadMessages()
{
string content = string.Empty;
//var request = OperationContext.Current.RequestContext.RequestMessage.GetBody<FileState>();
string request = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody<byte[]>());
}
CLIENT SIDE CODE
Content that I'm sending is:
string jsonData = "{ \"categoryid\":\"" + file.CategoryId + "\",\"fileId\":\"" + file.FileId + "\" }";
I tried many options to send data from the client like:
var buffer = System.Text.Encoding.UTF8.GetBytes(jsonData);
var content = new ByteArrayContent(buffer);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
and also tried this:
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
Posting request:
HttpResponseMessage executionResult = httpClient.PostAsync($"{url}/LoadMessages", content).Result;
I also tried serializing/de-serializing at client/server end, but that also is not working.
Can someone please suggest code samples what I can try that might work? Or point out what am I doing wrong.
A few more examples of what I tried with the JSON data :
var jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
var details = JObject.Parse(data);
Pasting my client side function for clarity:
HttpClient httpClient = new HttpClient(new HttpClientHandler());
HttpStatusCode statusCode = HttpStatusCode.OK;
string auditMessage = string.Empty;
using (httpClient)
{
var url = ConfigurationManager.AppSettings["APIURL"];
try
{
string jsonData = "{ \"categoryid\":\"" + file.CategoryId + "\",\"fileId\":\"" + file.FileId + "\" }";
//var jsonData = JsonConvert.SerializeObject(data, Formatting.Indented);
//var details = JObject.Parse(data);
//var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
var buffer = System.Text.Encoding.UTF8.GetBytes(jsonData);
var content = new ByteArrayContent(buffer);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage executionResult = httpClient.PostAsync($"{url}/LoadMessages", content).Result;
statusCode = executionResult.StatusCode;
if (statusCode == HttpStatusCode.Accepted)
{
file.Status = "Success";
}
}
catch (Exception ex)
{
}
}
Here is my demo:
This is the interface document of the service:
This is the request:
class Program
{
static void Main(string[] args)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:8012/ServiceModelSamples/service/user");
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-16";
string Json = "{\"Email\":\"123\",\"Name\":\"sdd\",\"Password\":\"sad\"}";
request.ContentLength = Encoding.UTF8.GetByteCount(Json);
Stream myRequestStream = request.GetRequestStream();
StreamWriter myStreamWriter = new StreamWriter(myRequestStream, Encoding.GetEncoding("gb2312"));
myStreamWriter.Write(Json);
myStreamWriter.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
//myResponseStream.ResponseSoapContext
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
Console.WriteLine(retString);
Console.ReadKey();
}
}
Feel free to let me know if the problem persists.
UPDATE
Define the Test class:
[DataContract]
public class Test {
[DataMember]
public string categoryid { get; set; }
[DataMember]
public string fileId { get; set; }
}
the implementation is as:
public void LoadMessages(Test test)
{
Test dataObject = OperationContext.Current.RequestContext.RequestMessage.GetBody<Test>(new DataContractJsonSerializer(typeof(Test)));
Console.WriteLine(dataObject.categoryid);
}

Open OSM pbf results in Protobuf exception

Using OSMSharp I am having trouble to open a stream for a file (which I can provide on demand)
The error occurs in PBFReader (line 104)
using (var tmp = new LimitedStream(_stream, length))
{
header = _runtimeTypeModel.Deserialize(tmp, null, _blockHeaderType) as BlobHeader;
}
and states: "ProtoBuf.ProtoException: 'Invalid field in source data: 0'" which might mean different things as I have read in this SO question.
The file opens and is visualized with QGis so is not corrupt in my opinion.
Can it be that the contracts do not match? Is OsmSharp/core updated to the latest .proto files for OSM from here (although not sure if this is the real original source for the definition files).
And what might make more sense, can it be that the file I attached is generated for v2 of OSM PBF specification?
In the code at the line of the exception I see the following comment which makes me wonder:
// TODO: remove some of the v1 specific code.
// TODO: this means also to use the built-in capped streams.
// code borrowed from: http://stackoverflow.com/questions/4663298/protobuf-net-deserialize-open-street-maps
// I'm just being lazy and re-using something "close enough" here
// note that v2 has a big-endian option, but Fixed32 assumes little-endian - we
// actually need the other way around (network byte order):
// length = IntLittleEndianToBigEndian((uint)length);
BlobHeader header;
// again, v2 has capped-streams built in, but I'm deliberately
// limiting myself to v1 features
So this makes me wonder if OSM Sharp is (still) up-to-date.
My sandbox code looks like this:
using OsmSharp.Streams;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OsmSharp.Tags;
namespace OsmSharp
{
class Program
{
private const string Path = #"C:\Users\Bernoulli IT\Documents\Applications\Argaleo\Test\";
private const string FileNameAntarctica = "antarctica-latest.osm";
private const string FileNameOSPbf = "OSPbf";
private const Boolean useRegisterSource = false;
private static KeyValuePair<string, string> KeyValuePair = new KeyValuePair<string, string>("joep", "monita");
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
//string fileName = $#"{Path}\{FileNameAntarctica}.pbf";
string fileName = $#"{Path}\{FileNameOSPbf}.pbf";
string newFileName = $"{fileName.Replace(".pbf", string.Empty)}-{Guid.NewGuid().ToString().Substring(0, 4)}.pbf";
Console.WriteLine("*** Complete");
string fileNameOutput = CompleteFlow(fileName, newFileName);
Console.WriteLine("");
Console.WriteLine("*** Display");
DisplayFlow(fileNameOutput);
Console.ReadLine();
}
private static string CompleteFlow(string fileName, string newFileName)
{
// 1. Open file and convert to bytes
byte[] fileBytes = FileToBytes(fileName);
// 2. Bytes to OSM stream source (pbf)
PBFOsmStreamSource osmStreamSource;
osmStreamSource = BytesToOsmStreamSource(fileBytes);
osmStreamSource.MoveNext();
if (osmStreamSource.Current() == null)
{
osmStreamSource = FileToOsmStreamSource(fileName);
osmStreamSource.MoveNext();
if (osmStreamSource.Current() == null)
{
throw new Exception("No current in stream.");
}
}
// 3. Add custom tag
AddTag(osmStreamSource);
// 4. OSM stream source to bytes
//byte[] osmStreamSourceBytes = OsmStreamSourceToBytes(osmStreamSource);
// 5. Bytes to file
//string fileNameOutput = BytesToFile(osmStreamSourceBytes, newFileName);
OsmStreamSourceToFile(osmStreamSource, newFileName);
Console.WriteLine(newFileName);
return newFileName;
}
private static void DisplayFlow(string fileName)
{
// 1. Open file and convert to bytes
byte[] fileBytes = FileToBytes(fileName);
// 2. Bytes to OSM stream source (pbf)
BytesToOsmStreamSource(fileBytes);
}
private static byte[] FileToBytes(string fileName)
{
Console.WriteLine(fileName);
return File.ReadAllBytes(fileName);
}
private static PBFOsmStreamSource BytesToOsmStreamSource(byte[] bytes)
{
MemoryStream memoryStream = new MemoryStream(bytes);
memoryStream.Position = 0;
PBFOsmStreamSource osmStreamSource = new PBFOsmStreamSource(memoryStream);
foreach (OsmGeo element in osmStreamSource.Where(osmGeo => osmGeo.Tags.Any(tag => tag.Key.StartsWith(KeyValuePair.Key))))
{
foreach (Tag elementTag in element.Tags.Where(tag => tag.Key.StartsWith(KeyValuePair.Key)))
{
Console.WriteLine("!!!!!!!!!!!!!! Tag found while reading !!!!!!!!!!!!!!!!!!".ToUpper());
}
}
return osmStreamSource;
}
private static PBFOsmStreamSource FileToOsmStreamSource(string fileName)
{
using (FileStream fileStream = new FileInfo(fileName).OpenRead())
{
PBFOsmStreamSource osmStreamSource = new PBFOsmStreamSource(fileStream);
return osmStreamSource;
}
}
private static void AddTag(PBFOsmStreamSource osmStreamSource)
{
osmStreamSource.Reset();
OsmGeo osmGeo = null;
while (osmGeo == null)
{
osmStreamSource.MoveNext();
osmGeo = osmStreamSource.Current();
if(osmGeo?.Tags == null)
{
osmGeo = null;
}
}
osmGeo.Tags.Add("joep", "monita");
Console.WriteLine($"{osmGeo.Tags.FirstOrDefault(tag => tag.Key.StartsWith(KeyValuePair.Key)).Key} - {osmGeo.Tags.FirstOrDefault(tag => tag.Key.StartsWith(KeyValuePair.Key)).Value}");
}
private static byte[] OsmStreamSourceToBytes(PBFOsmStreamSource osmStreamSource)
{
MemoryStream memoryStream = new MemoryStream();
PBFOsmStreamTarget target = new PBFOsmStreamTarget(memoryStream, true);
osmStreamSource.Reset();
target.Initialize();
UpdateTarget(osmStreamSource, target);
target.Flush();
target.Close();
return memoryStream.ToArray();
}
private static string BytesToFile(byte[] bytes, string fileName)
{
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
fs.Write(bytes, 0, bytes.Length);
}
return fileName;
}
private static void OsmStreamSourceToFile(PBFOsmStreamSource osmStreamSource, string fileName)
{
using (FileStream fileStream = new FileInfo(fileName).OpenWrite())
{
PBFOsmStreamTarget target = new PBFOsmStreamTarget(fileStream, true);
osmStreamSource.Reset();
target.Initialize();
UpdateTarget(osmStreamSource, target);
target.Flush();
target.Close();
}
}
private static void UpdateTarget(OsmStreamSource osmStreamSource, OsmStreamTarget osmStreamTarget)
{
if (useRegisterSource)
{
osmStreamTarget.RegisterSource(osmStreamSource, osmGeo => true);
osmStreamTarget.Pull();
}
else
{
bool isFirst = true;
foreach (OsmGeo osmGeo in osmStreamSource)
{
Tag? tag = osmGeo.Tags?.FirstOrDefault(t => t.Key == KeyValuePair.Key);
switch (osmGeo.Type)
{
case OsmGeoType.Node:
if (isFirst)
{
for (int indexer = 0; indexer < 1; indexer++)
{
(osmGeo as Node).Tags.Add(new Tag(KeyValuePair.Key + Guid.NewGuid(), KeyValuePair.Value));
}
isFirst = false;
}
osmStreamTarget.AddNode(osmGeo as Node);
break;
case OsmGeoType.Way:
osmStreamTarget.AddWay(osmGeo as Way);
break;
case OsmGeoType.Relation:
osmStreamTarget.AddRelation(osmGeo as Relation);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}
}
}
Already I posted this question on the GITHube page of OSMSharp as is linked here. Any help would be very appreciated.

Submitting a WebRequest from within a CLR Trigger

I just implemented a prototype solution for updating my caching server in real-time by assigning a CLR Trigger to a table so that whenever a certain column is updated the URL called from the trigger will update the caching server with the correct data.
It's working fine and the code is as follows:
[Microsoft.SqlServer.Server.SqlTrigger(Name = "AdStatusChanged", Target = "Ads", Event = "FOR UPDATE")]
public static void AdStatusChanged()
{
SqlTriggerContext triggContext = SqlContext.TriggerContext;
int adID = 0, adStatusID_Old = 0, adStatusID_New = 0;
if (triggContext.TriggerAction == TriggerAction.Update)
{
using (SqlConnection conn = new SqlConnection("context connection=true"))
{
conn.Open();
SqlCommand sqlComm = new SqlCommand();
SqlPipe sqlP = SqlContext.Pipe;
sqlComm.Connection = conn;
sqlComm.CommandText = "SELECT AdID, AdStatusID from INSERTED";
SqlDataReader reader = sqlComm.ExecuteReader();
if (reader.Read())
{
adID = reader.GetInt32(0);
adStatusID_New = reader.GetInt32(1);
}
reader.Close();
sqlComm.CommandText = "SELECT AdID, AdStatusID from DELETED WHERE AdID = " + adID;
reader = sqlComm.ExecuteReader();
if (reader.Read())
{
adID = reader.GetInt32(0);
adStatusID_Old = reader.GetInt32(1);
}
}
if (adID == 0 || adStatusID_New == adStatusID_Old)
{
// Check could be more thorough !
return;
}
WebResponse httpResponse = null;
try
{
string apiURL = string.Format("{0}/{1}", "http://localhost:14003/Home", "UpdateAdStatus?adID=" + adID + "&adStatusID=" + adStatusID_New);
var httpWebRequest = (HttpWebRequest)WebRequest.Create(apiURL);
httpWebRequest.Method = "GET";
httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
// check for successful response
}
catch (Exception ex)
{
Log("WebRequest from within SQL Server failed ! " + ex.Message);
}
finally
{
if (httpResponse != null)
{
httpResponse.Close();
}
}
}
}
I would like to have some expert/experienced views on the "CONS" of this approach regarding performance, deadlocks, sql crashing, or other areas that could be of potential concern.
Has anyone tried this (I'm sure many must have) and what was the result ? a successful implementation or did you revert to some other method or updating the cache real-time?

ASP.NET MVC TempData in browser cookie

I am trying to use a custom ITempDataProvider provider to store TempData in a browser's cookie instead of session state. However, everything works fine except that I am unable to remove the cookie from the Response stream after reading it.
Any ideas?
Thanks!
public class CookieTempDataProvider : ITempDataProvider
{
internal const string TempDataCookieKey = "__ControllerTempData";
HttpContextBase _httpContext;
public CookieTempDataProvider(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
_httpContext = httpContext;
}
public HttpContextBase HttpContext
{
get
{
return _httpContext;
}
}
protected virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
{
HttpCookie cookie = _httpContext.Request.Cookies[TempDataCookieKey];
if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
{
IDictionary<string, object> deserializedTempData = DeserializeTempData(cookie.Value);
// Remove cookie
cookie.Expires = DateTime.MinValue;
cookie.Value = string.Empty;
_httpContext.Request.Cookies.Remove(TempDataCookieKey);
if (_httpContext.Response != null && _httpContext.Response.Cookies != null)
{
HttpCookie responseCookie = _httpContext.Response.Cookies[TempDataCookieKey];
if (responseCookie != null)
{
// Remove cookie
cookie.Expires = DateTime.MinValue;
cookie.Value = string.Empty;
_httpContext.Response.Cookies.Remove(TempDataCookieKey);
}
}
return deserializedTempData;
}
return new Dictionary<string, object>();
}
protected virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
string cookieValue = SerializeToBase64EncodedString(values);
var cookie = new HttpCookie(TempDataCookieKey);
cookie.HttpOnly = true;
cookie.Value = cookieValue;
_httpContext.Response.Cookies.Add(cookie);
}
public static IDictionary<string, object> DeserializeTempData(string base64EncodedSerializedTempData)
{
byte[] bytes = Convert.FromBase64String(base64EncodedSerializedTempData);
var memStream = new MemoryStream(bytes);
var binFormatter = new BinaryFormatter();
return binFormatter.Deserialize(memStream, null) as IDictionary<string, object> /*TempDataDictionary : This returns NULL*/;
}
public static string SerializeToBase64EncodedString(IDictionary<string, object> values)
{
MemoryStream memStream = new MemoryStream();
memStream.Seek(0, SeekOrigin.Begin);
var binFormatter = new BinaryFormatter();
binFormatter.Serialize(memStream, values);
memStream.Seek(0, SeekOrigin.Begin);
byte[] bytes = memStream.ToArray();
return Convert.ToBase64String(bytes);
}
IDictionary<string, object> ITempDataProvider.LoadTempData(ControllerContext controllerContext)
{
return LoadTempData(controllerContext);
}
void ITempDataProvider.SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
SaveTempData(controllerContext, values);
}
}
There is a better solution by Brock Allen on GitHub that uses encryption, 2 forms of serialization, and compression to protect and optimize the cookies.
https://github.com/brockallen/CookieTempData
Here is a link to the blog about it:
http://brockallen.com/2012/06/11/cookie-based-tempdata-provider/
He also has a good technique using IControllerFactory to ensure every controller is supplied with an instance of ITempDataProvider.
Hi I too had the same issue and it was an issue with the implementation of CookieTempDataProvider.
So I modified the code a bit and now it works perfectly.
When it reads the data from the cookie, it removes it from both the request and response. But add another cookie with an empty value in the SaveData function which is called when the request processing is completed.
Points to note : If you want to remove a cookie, you have to set the timeout value and send it back to the client and then the browser will remove it. We cannot do it otherwise from the code a the cookie is handled by the browser
And I found out that setting the expiration to DateTime.MinValue does not expire the cookie in chrome (don't know about the other browsers) so I set it to 2001-01-01 :)
Here is the working code
public class CookieTempDataProvider : ITempDataProvider
{
internal const string TempDataCookieKey = "__ControllerTempData";
HttpContextBase _httpContext;
public CookieTempDataProvider(HttpContextBase httpContext)
{
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
_httpContext = httpContext;
}
public HttpContextBase HttpContext
{
get
{
return _httpContext;
}
}
protected virtual IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
{
if (_httpContext.Request.Cookies.AllKeys.Contains(TempDataCookieKey)) //we need this because
//Cookies[TempDataCookieKey] will create the cookie if it does not exist
{
HttpCookie cookie = _httpContext.Request.Cookies[TempDataCookieKey];
if (cookie != null && !string.IsNullOrEmpty(cookie.Value))
{
IDictionary<string, object> deserializedTempData = DeserializeTempData(cookie.Value);
// Remove cookie
cookie.Expires = new DateTime(2000, 1, 1);
cookie.Value = string.Empty;
_httpContext.Request.Cookies.Remove(TempDataCookieKey);
if (_httpContext.Response != null && _httpContext.Response.Cookies != null)
{
HttpCookie responseCookie = _httpContext.Response.Cookies[TempDataCookieKey];
if (responseCookie != null)
{
// Remove cookie
cookie.Expires = new DateTime(2000, 1, 1);
cookie.Value = string.Empty;
_httpContext.Response.Cookies.Remove(TempDataCookieKey);
}
}
return deserializedTempData;
}
}
return new Dictionary<string, object>();
}
protected virtual void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
if (values != null && values.Count > 0)
{
//there are values to set, so add the cookie. But no need to expire it as we need the browser to send the
//cookie back with the next request
string cookieValue = SerializeToBase64EncodedString(values);
var cookie = new HttpCookie(TempDataCookieKey);
cookie.HttpOnly = true;
cookie.Value = cookieValue;
_httpContext.Response.Cookies.Add(cookie);
}
else
{
//Still we need to add the cookie with the expiration set, to make the client browser remove the cookie from the request.
//Otherwise the browser will continue to send the cookie with the response
//Also we need to do this only if the requet had a tempdata cookie
if (_httpContext.Request.Cookies.AllKeys.Contains(TempDataCookieKey))
{
{
HttpCookie cookie = _httpContext.Request.Cookies[TempDataCookieKey];
// Remove the request cookie
cookie.Expires = new DateTime(2000, 1, 1);
cookie.Value = string.Empty;
_httpContext.Request.Cookies.Remove(TempDataCookieKey);
var rescookie = new HttpCookie(TempDataCookieKey);
rescookie.HttpOnly = true;
rescookie.Value = "";
rescookie.Expires = new DateTime(2000, 1, 1); //so that the browser will remove the cookie when it receives the request
_httpContext.Response.Cookies.Add(rescookie);
}
}
}
}
public static IDictionary<string, object> DeserializeTempData(string base64EncodedSerializedTempData)
{
byte[] bytes = Convert.FromBase64String(base64EncodedSerializedTempData);
var memStream = new MemoryStream(bytes);
var binFormatter = new BinaryFormatter();
return binFormatter.Deserialize(memStream, null) as IDictionary<string, object> /*TempDataDictionary : This returns NULL*/;
}
public static string SerializeToBase64EncodedString(IDictionary<string, object> values)
{
MemoryStream memStream = new MemoryStream();
memStream.Seek(0, SeekOrigin.Begin);
var binFormatter = new BinaryFormatter();
binFormatter.Serialize(memStream, values);
memStream.Seek(0, SeekOrigin.Begin);
byte[] bytes = memStream.ToArray();
return Convert.ToBase64String(bytes);
}
IDictionary<string, object> ITempDataProvider.LoadTempData(ControllerContext controllerContext)
{
return LoadTempData(controllerContext);
}
void ITempDataProvider.SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
SaveTempData(controllerContext, values);
}
}
Here is an example of a working solution without lots of excess code. It uses Json.NET for serializing, which is faster than BinaryFormatter + Base64Encoding and also produces a much shorter string (=less http overhead).
public class CookieTempDataProvider : ITempDataProvider
{
const string cookieKey = "temp";
public IDictionary<string, object> LoadTempData(ControllerContext controllerContext)
{
var cookie = controllerContext.HttpContext.Request.Cookies[cookieKey];
if (cookie != null) {
return JsonConvert.DeserializeObject<IDictionary<string, object>>(cookie.Value);
}
return null;
}
// Method is called after action execution. The dictionary mirrors the contents of TempData.
// If there are any values in the dictionary, save it in a cookie. If the dictionary is empty,
// remove the cookie if it exists.
public void SaveTempData(ControllerContext controllerContext, IDictionary<string, object> values)
{
var ctx = controllerContext.HttpContext;
if (values.Count > 0) {
var cookie = new HttpCookie(cookieKey)
{
HttpOnly = true,
Value = JsonConvert.SerializeObject(values)
};
ctx.Response.Cookies.Add(cookie);
} else if (ctx.Request.Cookies[cookieKey] != null) {
// Expire cookie to remove it from browser.
ctx.Response.Cookies[cookieKey].Expires = DateTime.Today.AddDays(-1);
}
}
}

ASP.NET JSON Web Service Response format

I have written one simple web service which get product list in JSONText which is string object
Web Service code is below
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Text;
/// <summary>
/// Summary description for JsonWebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class JsonWebService : System.Web.Services.WebService
{
public JsonWebService () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string GetProductsJson(string prefix)
{
List<Product> products = new List<Product>();
if (prefix.Trim().Equals(string.Empty, StringComparison.OrdinalIgnoreCase))
{
products = ProductFacade.GetAllProducts();
}
else
{
products = ProductFacade.GetProducts(prefix);
}
//yourobject is your actula object (may be collection) you want to serialize to json
DataContractJsonSerializer serializer = new DataContractJsonSerializer(products.GetType());
//create a memory stream
MemoryStream ms = new MemoryStream();
//serialize the object to memory stream
serializer.WriteObject(ms, products);
//convert the serizlized object to string
string jsonString = Encoding.Default.GetString(ms.ToArray());
//close the memory stream
ms.Close();
return jsonString;
}
}
now it give me resoponse like below :
{"d":"[{\"ProductID\":1,\"ProductName\":\"Product 1\"},{\"ProductID\":2,\"ProductName\":\"Product 2\"},{\"ProductID\":3,\"ProductName\":\"Product 3\"},{\"ProductID\":4,\"ProductName\":\"Product 4\"},{\"ProductID\":5,\"ProductName\":\"Product 5\"},{\"ProductID\":6,\"ProductName\":\"Product 6\"},{\"ProductID\":7,\"ProductName\":\"Product 7\"},{\"ProductID\":8,\"ProductName\":\"Product 8\"},{\"ProductID\":9,\"ProductName\":\"Product 9\"},{\"ProductID\":10,\"ProductName\":\"Product 10\"}]"}
But i am looking for below out put
[{"ProductID":1,"ProductName":"Product 1"},{"ProductID":2,"ProductName":"Product 2"},{"ProductID":3,"ProductName":"Product 3"},{"ProductID":4,"ProductName":"Product 4"},{"ProductID":5,"ProductName":"Product 5"},{"ProductID":6,"ProductName":"Product 6"},{"ProductID":7,"ProductName":"Product 7"},{"ProductID":8,"ProductName":"Product 8"},{"ProductID":9,"ProductName":"Product 9"},{"ProductID":10,"ProductName":"Product 10"}]
can any one tell me what is actual problem
Thanks
First there was a change with ASP.NET 3.5 for security reasons Microsoft added the "d" to the response. Below is a link from Dave Ward at the Encosia that talks about what your seeing:
A breaking change between versions of ASP.NET AJAX. He has several posts that talks about this that can help you further with processing JSON and ASP.NET
Actually, if you just remove the
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
from the method, and you return the jsonString that you serialized using the JavaScriptSerializer you will get exactelly the output that you were looking for.
Notice that u have double quotes beside ur array in your response.In this way u return json format not json object from ur web method.Json format is a string.Therefore u have to use json.parse() function in order to parse json string to json object.If u dont want to use parse fuction,u have to remove serialize in ur web method.Thus u get a json object.
in .net web service
[WebMethod]
public string Android_DDD(string KullaniciKey, string Durum, string PersonelKey)
{
return EU.EncodeToBase64("{\"Status\":\"OK\",\"R\":[{\"ImzaTipi\":\"Paraf\", \"Personel\":\"Ali Veli üğişçöıÜĞİŞÇÖI\", \"ImzaDurumTipi\":\"Tamam\", \"TamamTar\":\"1.1.2003 11:21\"},{\"ImzaTipi\":\"İmza\", \"Personel\":\"Ali Ak\", \"ImzaDurumTipi\":\"Tamam\", \"TamamTar\":\"2.2.2003 11:21\"}]}");
}
static public string EncodeToBase64(string toEncode)
{
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(toEncode);
string returnValue = System.Convert.ToBase64String(bytes);
return returnValue;
}
in android
private static String convertStreamToString(InputStream is)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try
{
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
return sb.toString();
}
private void LoadJsonDataFromASPNET()
{
try
{
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(this.WSURL + "/WS.asmx/Android_DDD");
JSONObject jsonObjSend = new JSONObject();
jsonObjSend.put("KullaniciKey", "value_1");
jsonObjSend.put("Durum", "value_2");
jsonObjSend.put("PersonelKey", "value_3");
StringEntity se = new StringEntity(jsonObjSend.toString());
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
// httpPostRequest.setHeader("Accept-Encoding", "gzip"); // only set this parameter if you would like to use gzip compression
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
HttpEntity entity = response.getEntity();
if (entity != null)
{
InputStream instream = entity.getContent();
String resultString = convertStreamToString(instream);
instream.close();
resultString = resultString.substring(6, resultString.length()-3);
resultString = new String(android.util.Base64.decode(resultString, 0), "UTF-8");
JSONObject object = new JSONObject(resultString);
String oDurum = object.getString("Status");
if (oDurum.equals("OK"))
{
JSONArray jsonArray = new JSONArray(object.getString("R"));
if (jsonArray.length() > 0)
{
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject jsonObject = jsonArray.getJSONObject(i);
String ImzaTipi = jsonObject.getString("ImzaTipi");
String Personel = jsonObject.getString("Personel");
String ImzaDurumTipi = jsonObject.getString("ImzaDurumTipi");
String TamamTar = jsonObject.getString("TamamTar");
Toast.makeText(getApplicationContext(), "ImzaTipi:" + ImzaTipi + " Personel:" + Personel + " ImzaDurumTipi:" + ImzaDurumTipi + " TamamTar:" + TamamTar, Toast.LENGTH_LONG).show();
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}