Send multiple of items to WCF Dataservice at once? - c#

I'm using WCF Data Service as a way to allow other webservice in the project to connect to the database. My problem is that I our project has a crawler that add tens of items to the database every hour.
Using AddToItems method (which is auto generated by ADO.NET) leads to timeout exception or at least it makes the crawler in need to wait for a lot of time taking into consideration that Addto method handles each independently.
*Notes :
1- I've added an interceptor on adding to items to perform some actions when a new item is added.
2- WCF Data services Service Operations doesn't allow taking parameters of a user defined data type , that prevented me from creating a service operation that takes a list of items as a parameter to be able to handle multiple items at each time and at the same way to allow the client to handle it asynchronously.
When I tried to serialize this list so it can be treated as a string , an exception has occurred because of the length limit of the url even when POST is used instead of Get.
Update : Saveing Changes via BeginSaveChanged and EndSaveChanged solved the problem to some extent but I'm still looking for a better solution

Maybe the OData feature Batch can address your requirement:
var client = new Container(serviceUrl);
client.Format.UseJson();
DefaultBatchCustomer customer0ToAdd = new DefaultBatchCustomer { Id = 10, Name = "Customer 10" };
DefaultBatchCustomer customer0ToAdd = new DefaultBatchCustomer { Id = 11, Name = "Customer 11" };
client.AddToDefaultBatchCustomer(customer0ToAdd);
client.AddToDefaultBatchCustomer(customer1ToAdd);
var response = await client.SaveChangesAsync(SaveChangesOptions.BatchWithSingleChangeset);
and the request looks like:
POST http://jinfutanwebapi1:9123/DefaultBatch/$batch HTTP/1.1
OData-Version: 4.0;NetFx
OData-MaxVersion: 4.0;NetFx
Content-Type: multipart/mixed; boundary=batch_8ce61768-e8bb-4117-954b-9bc43e05baef
Accept: multipart/mixed
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
Host: jinfutanwebapi1:9123
Content-Length: 1772
Expect: 100-continue
--batch_8ce61768-e8bb-4117-954b-9bc43e05baef
Content-Type: multipart/mixed; boundary=changeset_b36bec94-fc3b-4d89-99cc-0610fcec8148
--changeset_b36bec94-fc3b-4d89-99cc-0610fcec8148
Content-Type: application/http
Content-Transfer-Encoding: binary
POST http://jinfutanwebapi1:9123/DefaultBatch/DefaultBatchCustomer HTTP/1.1
Content-ID: 13
OData-Version: 4.0;NetFx
OData-MaxVersion: 4.0;NetFx
Content-Type: application/json;odata.metadata=minimal
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
{"#odata.type":"#WebStack.QA.Test.OData.Batch.Tests.DataServicesClient.DefaultBatchCustomer","Id":10,"Name":"Customer 10"}
--changeset_b36bec94-fc3b-4d89-99cc-0610fcec8148
Content-Type: application/http
Content-Transfer-Encoding: binary
POST http://jinfutanwebapi1:9123/DefaultBatch/DefaultBatchCustomer HTTP/1.1
Content-ID: 14
OData-Version: 4.0;NetFx
OData-MaxVersion: 4.0;NetFx
Content-Type: application/json;odata.metadata=minimal
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
{"#odata.type":"#WebStack.QA.Test.OData.Batch.Tests.DataServicesClient.DefaultBatchCustomer","Id":11,"Name":"Customer 11"}
--changeset_b36bec94-fc3b-4d89-99cc-0610fcec8148--
--batch_8ce61768-e8bb-4117-954b-9bc43e05baef--

Related

How to make multipart/mixed request containing nested HTTP requests

I am trying to implement creating a multipart request where each part is a HTTP request
To see what I mean here's for example how this Google API works: https://cloud.google.com/dns/api/batch#example (I don't use that API, it's just an example)
I've seen examples using MultipartFormDataContent but I don't understand how to create each part"
--====1340674896===
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1111
POST /contacts/479038 HTTP/1.1
Content-Type: application/json
Accept: application/json
{ "SomeData" : 1 }
The content of each part is I think the serialized string of a request:
GET /contacts/479038 HTTP/1.1
Content-Type: application/json
Accept: application/json
{ "SomeData" : 1 }
So how do I create this? I guess I need to get the serialized version of a HttpRequestMessage?
Can I just serialize request.Content.ReadAsStringAsync())
In WebAPI I see there's this HttpContentMessage which takes a HttpRequestMessage and can serialize it:
var httpMessageContent = new HttpMessageContent(request);
var buffer = httpMessageContent.ReadAsByteArrayAsync().Result;
stream.Write(buffer, 0, buffer.Length);
But I don't have this class available in .NETStandard

Microsoft Graph List OneDrive Items

I want to list all my OneDrive for Business Items in an UWP-Application. For this I'm using "Microsoft Graph Client Library" from NuGet. It's a wrapper Library for the Microsoft Graph REST-API.
When I'm trying to get all items or children (I tried both) from my root-drive or from an spezific Folder-ID, I just get an empty List. But there are different Files and Folders in my Drive. Even when I'm using the REST-API without this wrapper, I'm getting just an empty Result.
But when I'm using the "Recent" function, I'm getting a list of my recent used Items.
// Returns an empty result without error
GraphServiceClient.Me.Drive.Items.Request().GetAsync()
GraphServiceClient.Me.Drive.Root.Children.Request().GetAsync()
GraphServiceClient.Drives["id"].Items.Request().GetAsync()
// Returns all my recent used items
GraphServiceClient.Me.Drive.Recent().Request().GetAsync()
GraphServiceClient.Drives["id"].Recent().Request().GetAsync()
The HTTP-Traffic Looks like:
GET https://graph.microsoft.com/v1.0/me/drive/root/children HTTP/1.1
SdkVersion: graph-dotnet-1.0.1
Cache-Control: no-store, no-cache
Authorization: Bearer 1234567890123456789
Host: graph.microsoft.com
Connection: Keep-Alive
// Response:
HTTP/1.1 200 OK
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8
Server: Microsoft-IIS/8.5
request-id: 123456-7890123
client-request-id: 123456-7890123
x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"West Europe","Slice":"SliceB","ScaleUnit":"000","Host":"AGSFE_IN_3","ADSiteName":"AMS"}}
OData-Version: 4.0
Duration: 823.6454
X-Powered-By: ASP.NET
Date: Wed, 15 Jun 2016 06:56:29 GMT
8c
{"#odata.context":"https://graph.microsoft.com/v1.0/$metadata#users('123456-7890123-456789')/drive/root/children","value":[]}
0
(I've removed the Id's, so thats not the Problem)
Can someone help?
To get the items from OneDrive using the Microsoft Graph, we need to make the request to the endpoint. The ‘Request’ method didn’t make the real request until we call ‘GetAsync’ method.
Here is an example that get the children items of the default drive:
var items = await graphserviceClient.Me.Drive.Root.Children.Request().GetAsync();
Refer to here for more detail about this SDK.

ASP.NET WebAPI - Issues with [FromBody]

I'm looking to implement a new API but rather than going down my usual route of PHP I've opted for C#.
I've had a little play with the 'MVC 4 API' example, but so far I can't seem to get my requests working.
I've created a controller called 'Values' and have the following method:
[HttpPost]
public void Post([FromBody]string value)
{
string body = value;
}
I've then sent the following POST request via fiddler to said API:
User-Agent: Fiddler
Host: localhost:56501
Content-Length: 10
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
value=test
After running this, it looks as though the method is being called, but when attempting to get the 'value' sent through the body, it doesn't seem to pick up on it and instead gives me a null.
I can't seem to make it work for Content-Type: application/x-www-form-urlencoded, but this should work meanwhile :)
User-Agent: Fiddler
Host: localhost:56501
Content-Length: 6
Content-Type: application/json; charset=UTF-8
"test"
So I found out that if you need to make it work with application/x-www-form-urlencoded then you only need to pass =value as the body of your request. Definitely weird, but I guess this is not MVC, it's WebApi, so you shouldn't be passing application/x-www-form-urlencoded anyway ;)

Get Request Content of PUT method in WCF

I am trying to fetch "PUT" request content which is VCard via WCF.
here is its content,
PUT https://mysite.com/
Host: mysite.com
Content-Type: text/vcard; charset=utf-8
Accept-Encoding: gzip, deflate
Connection: keep-alive
Proxy-Connection: keep-alive
Accept: */*
Content-Length: 280
Accept-Language: en-us
BEGIN:VCARD
VERSION:3.0
N:test;Syeda;;;
FN:Syeda test
item1.EMAIL;type=INTERNET;type=pref:test#hotmail.com
TEL;type=HOME;type=VOICE;type=pref:021 3123456
REV:2013-12-09T13:51:45Z
UID:318D8B19-BBC0-4841-A831-89E224C27A2D
END:VCARD
when i am trying to fetch it it is giving the following error,
Expecting element 'string' from namespace 'http://schemas.microsoft.com/2003/10/Serialization/'.. Encountered 'Element' with name 'Binary', namespace ''.
Is there any workaroung anybody knows to access VCard content.
Though, i am able to get those request's content that is in Xml format.
Thanks!
Update:
Previously, i was fetching the request content using this line of code.
operationContext.RequestContext.RequestMessage.ToString()
This work fine until the request is in xml format.But, when request is bringing content given above it returns word "Stream" as a string.
And, when i tried to do something like this,
operationContext.RequestContext.RequestMessage.GetBody<String>();
I am getting error shown above.

Cache-Control Headers in ASP.NET

I am trying to set the cache-control headers for a web application (and it appears that I'm able to do it), but I am getting what I think are odd entries in the header responses. My implementation is as follows:
protected override void OnLoad(EventArgs e)
{
// Set Cacheability...
DateTime dt = DateTime.Now.AddMinutes(30);
Response.Cache.SetExpires(dt);
Response.Cache.SetMaxAge(new TimeSpan(dt.ToFileTime()));
// Complete OnLoad...
base.OnLoad(e);
}
And this is what the header responses show:
-----
GET /Pages/Login.aspx HTTP/1.1
Host: localhost:1974
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
X-lori-time-1: 1244048076221
Cache-Control: max-age=0
HTTP/1.x 200 OK
Server: ASP.NET Development Server/8.0.0.0
Date: Wed, 03 Jun 2009 16:54:36 GMT
X-AspNet-Version: 2.0.50727
Content-Encoding: gzip
Cache-Control: private, max-age=31536000
Expires: Wed, 03 Jun 2009 17:24:36 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 6385
Connection: Close
-----
Why does the "Cache-Control" property show up twice?
Do I need both "Cache-Control" and the "Expires" properties?
Is "Page_Load" the best place to put this code?
Thanks!
You might also want to add this line if you are setting the max age that far out :
// Summary:
// Sets Cache-Control: public to specify that the response is cacheable
// by clients and shared (proxy) caches.
Response.Cache.SetCacheability(HttpCacheability.Public);
I do a lot of response header manip with documents and images from a file handler that processes requests for files the are saved in the DB.
Depending on your goal you can really force the browsers the cache almost all of you page for days locally ( if thats what u want/need ).
edit:
I also think you might be setting the max age wrong...
Response.Cache.SetMaxAge(new TimeSpan(dt.Ticks - DateTime.Now.Ticks ));
this line set is to 30 min cache time on the local browser [max-age=1800]
As for the 2x Cache Control lines... you might want to check to see if IIS has been set to add the header automatically.
I don't see Cache-control appearing twice. One is in the request, one is in the response. The one in the request is probably because you hit Shift+F5 in the browser or something similar.
To your second question: that depends on what you want to achieve with the cache headers.
I don't know what you wanted to achieve with the max-age. The value is way too high since you converted the DateTime incorrectly to a TimeSpan. Why don't you just use TimeSpan.FromMinutes instead?
Page load is okay. I usually mess around with HTTP headers there myself.

Categories

Resources