EntityClassGenerator : Not generating any output for NorthwindDataService - odata

I am trying to generate the OData Proxy for the service : http://services.odata.org/Northwind/Northwind.svc/$metadata
I am using System.Data.Services.Design.EntityClassGenerator for generating the OData proxy.
When I instantiate the EntityClassGenerator and call GenerateCode the output has no errors. But there is no code in the generated proxy code.
The same code works for my own service. But when I point it to any external service the EntityClassGenerator is not working.
Here is the code :
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(metadataEndpoint);
webRequest.Method = "GET";
webRequest.ContentType = "text/xml;encoding='utf-8";
webRequest.Proxy = (proxy != null) ? proxy : WebRequest.DefaultWebProxy;
using (WebResponse response = webRequest.GetResponse())
{
string xml = string.Empty;
XmlReaderSettings settings = new XmlReaderSettings();
using (TextReader reader = new StreamReader(response.GetResponseStream()))
{
xml = reader.ReadToEnd();
using (XmlTextReader sourceReader = new XmlTextReader(reader))
{
using (StringWriter targetWriter = new StringWriter())
{
// Generate the OData End point proxy.
EntityClassGenerator entityGenerator = new EntityClassGenerator(LanguageOption.GenerateCSharpCode);
entityGenerator.OnPropertyGenerated += new EventHandler<PropertyGeneratedEventArgs>(entityGenerator_OnPropertyGenerated);
IList<System.Data.Metadata.Edm.EdmSchemaError> errors = entityGenerator.GenerateCode(sourceReader, targetWriter, namespacename);
entityGenerator.OnPropertyGenerated -= new EventHandler<PropertyGeneratedEventArgs>(entityGenerator_OnPropertyGenerated);
odataProxyCode = targetWriter.ToString();
}
}
}
}

I found the code in the question to be a useful starting point for doing exactly what the OP was asking. So even though the OP doesn't accept answers, I'll describe the changes I made to get it to work in case it is useful to someone else.
Removed the xml = reader.ReadToEnd(); call. I assume that was for debugging purposes to look at the response from the web request, but it had the result of "emptying" the reader object of the response. That meant that there was nothing left in the reader for the GenerateCode call.
The important one: Changed the use of EntityClassGenerator to System.Data.Services.Design.EntityClassGenerator. In the code below, I included the entire name space for clarity and specificity. Based on the code in the question, it appears the OP was probably using System.Data.Entity.Design.EntityClassGenerator. I used .NET Reflector to examine datasvcutil.exe, which is a command-line utility that can generate the proxy classes. I saw that it referenced the generator in that other name space.
For figuring out the problems, I dumped the errors from the GenerateCode call. One could examine them in the debugger, but some kind of automated checking of them would be needed regardless.
Here is what I ended up with:
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.
Create("http://services.odata.org/Northwind/Northwind.svc/$metadata");
webRequest.Method = "GET";
webRequest.ContentType = "text/xml;encoding='utf-8";
webRequest.Proxy = WebRequest.DefaultWebProxy;
using (WebResponse response = webRequest.GetResponse())
{
using (TextReader reader = new StreamReader(response.GetResponseStream()))
{
using (XmlTextReader sourceReader = new XmlTextReader(reader))
{
using (StringWriter targetWriter = new StringWriter())
{
// Generate the OData End point proxy.
System.Data.Services.Design.EntityClassGenerator entityGenerator =
new System.Data.Services.Design.EntityClassGenerator(
System.Data.Services.Design.LanguageOption.GenerateCSharpCode);
IList<System.Data.Metadata.Edm.EdmSchemaError> errors =
entityGenerator.GenerateCode(sourceReader, targetWriter,
"My.Model.Entities");
foreach (System.Data.Metadata.Edm.EdmSchemaError error in errors)
Console.WriteLine("{0}: {1}", error.Severity.ToString(), error.Message);
string odataProxyCode = targetWriter.ToString();
}
}
}
}

Related

Google Machine Learning API Issue

I'm trying to use the Google Machine Learning API and I'm facing two problems.
In the API explorer I put the correct information and I get a response error:
Code 200
"error": "Missing \"instances\" field in request body: {\n \"httpBody\": \n
{\n \"data\": \"\\"instances\\" : \\"teste\\"\",\n
\"contentType\": \"application/json\"\n }\n}"
The request find my model (if I change the value in field name I get another error) but don't understand my json. That's the json:
{"instances" : [{"key":"0", "image_bytes": {"b64": "mybase64"} }]}
When I do the predict on the command line using gcloud, I get no errors and everything seems ok. The Json that I was create for gcloud is a little bit different:
{"key":"0", "image_bytes": {"b64": "mybase64"} }
I already tryied that one in the API explorer and no success.
So, I decided to use the .Net Api to try the predict and I get other situation: The Response is Empty (???).
Here is my code:
'get the service credential that I created
Dim credential = Await GetCredential()
Dim myService As New CloudMachineLearningEngineService(New BaseClientService.Initializer() With {
.ApplicationName = "my Project Name (Is That It???)",
.ApiKey = "my API Key",
.HttpClientInitializer = credential
})
Dim myBase64 As String = GetBase64("my image path to convert into a base64 String")
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
'If I change the model name I get error
Dim myPredictRequest = myService.Projects.Predict(myRequest, "projects/myProject/models/myModel/versions/v1")
myPredictRequest.AccessToken = credential.Token.AccessToken
myPredictRequest.OauthToken = credential.Token.AccessToken
myPredictRequest.Key = "my API Key
'Execute the request
Dim myResponse = myPredictRequest.Execute()
'at this point, myResponse is Empty (myResponse.ContentType Is Nothing, myResponse.Data Is Nothing And myResponse.ETag Is Nothing)
If I change the model name I get a error informing that my model was not found, so my credentials are right.
I don't know what I'm doing wrong. Someboby can help with any of this issues?
Thanks!
UPDATE: --------------------------
I changed this Execute Command:
Dim myResponse = myPredictRequest.Execute()
To This One:
Dim s = StreamToString(myPredictRequest.ExecuteAsStream())
and Now I can get the same error with .Net API and google developers interface (Missing instances field...).
So If someboby just Know what is wrong with my Json request, It will help a lot.
The JSON you put in the API explorer is indeed correct (assuming, of course, your model has inputs key and image_bytes). This appears to be a bug with the explorer I will report.
The reason you are getting the error you are in the .NET code is because you are using an .HttpBody field. This code:
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
Will produce a JSON request that looks like this:
{
"httpBody": {
"data": "{\"instances\" : [{\"key\":\"0\", \"image_bytes\": {\"b64\": \"mybase64\"} }]}",
"contentType": "application\/json"
}
}
When what you really need is:
{"instances" : [{"key":"0", "image_bytes": {"b64": "mybase64"} }]}
Hence the error message you see.
I don't know how to generate the correct response using the .NET library; based on the Python example in the docs, I would guess:
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myPredictRequest = myService.Projects.Predict(myJsonRequest, "projects/myProject/models/myModel/versions/v1")
But I don't have a good way of testing that. For reference, the Python equivalent is:
response = service.projects().predict(
name=name,
body=myJsonRequest
).execute()
I solved the problem with .Net API.
I created two new classes Inherits the Google API's classes.
Something like that:
Imports Google.Apis.CloudMachineLearningEngine.v1.Data
Imports Newtonsoft.Json
Public Class myGoogleCloudMlV1PredictRequest
Inherits GoogleCloudMlV1PredictRequest
<JsonProperty("instances")>
Public Property MyHttpBody As List(Of myGoogleApiHttpBody)
End Class
Imports Google.Apis.CloudMachineLearningEngine.v1.Data
Imports Newtonsoft.Json
Public Class myGoogleApiHttpBody
Inherits GoogleApiHttpBody
<JsonProperty("image_bytes")>
Public Property MyData As image_byte
<JsonProperty("key")>
Public Property key As String
End Class
So, in my original code I change this part:
Dim myBase64 As String = GetBase64("my_image_path_to_convert_into_a _base64_String")
Dim myJsonRequest As String = "{""instances"" : [{""key"":""0"", ""image_bytes"": {""b64"": """ + myBase64 + """}}]}"
Dim myRequest = New GoogleCloudMlV1PredictRequest With {
.HttpBody = New GoogleApiHttpBody With {.Data = myJsonRequest,
.ContentType = "application/json"
}
}
For this one:
Dim myBase64 As String = GetBase64("my_image_path_to_convert_into_a _base64_String")
Dim myRequest = New myGoogleCloudMlV1PredictRequest With {
.MyHttpBody = New List(Of myGoogleApiHttpBody)()
}
Dim item As myGoogleApiHttpBody = New myGoogleApiHttpBody With {
.key = "0",
.MyData = New image_byte With {
.b64 = myBase64
}
}
myRequest.MyHttpBody.Add(item)
And voilá, It's working!
Thanks for everyone!!
Github issue #1068 shows two work-arounds for this problem.
In summary, use service.ModifyRequest to insert the raw JSON content.
Or use service.HttpClient.PostAsync(...) directly.

Setting ContentType causing multiple requests in MVC Web API

I have a simple GetFile Method in a Web API that returns a file stored as binary in a database. The file can be either image, video or a recording, so I set the content type based on the extension:
[System.Web.Mvc.HttpGet]
public HttpResponseMessage GetFile(Guid Id)
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
var file = db.Files.Where<NonConformityFile>(item => item.Id == Id).FirstOrDefault<NonConformityFile>();
byte[] imgData = file.FileContents;
MemoryStream ms = new MemoryStream(imgData);
response.Content = new StreamContent(ms);
if (file.FileExtension == "png")
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png");
else if (file.FileExtension == "mp4")
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("video/mp4");
else if (file.FileExtension == "caf")
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("audio/x-caf");
else
throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.UnsupportedMediaType, file.FileExtension + " is not a supported file format"));
return response;
}
This Works fine, but when adding some Security to the Method (by providing a token in the http header) it started crashing. When setting a breakpoint, I discovered that the breakpoint was actually hit twice. And the second time the token was gone from the header, causing authentication failure.
Further debugging made me find out that setting the response.Content.Header.ContentType causes the GetFile Method to be called a second time.
Is this designed behaviour, or some crazy side effects from something in my Development environment?
To reproduce, try this:
[System.Web.Mvc.HttpGet]
public HttpResponseMessage GetFile()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
response.Content = new StreamContent(new MemoryStream());
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png");
return response;
}
And see if the Method is run twice. I cannot see the Logic in this behaviour, and it is causing problems in my authentication.

rails post parameter truncated

I have an oddity I hope someone can help with, I have an application which is uploading a reasonably long string as a post parameter, I know the web request is right because it works fine with PHP.
With Rails 4 though it seems to just chop off the string at the same point every time, yet I can't find any documentation that indicates this is normal behavior i'm assigning it like so:
mystring= params[:post_xml]
if I do the following:
mystring = request.body.read
It works fine!
Any ideas?
EDIT For clarity here's my C# request code its on port 3001 as thats the test port for rails
HttpWebRequest httpWReq = (HttpWebRequest)WebRequest.Create("http://mydomain.com:3001/api/new");
ASCIIEncoding encoding = new ASCIIEncoding();
var textFromDoc = Globals.ThisAddIn.Application.ActiveDocument.Content.Text;
// string postData = "content=" + textFromDoc;
//byte[] data = encoding.GetBytes(postData);
byte[] data = Encoding.UTF8.GetBytes(textFromDoc);
httpWReq.Method = "POST";
httpWReq.ContentType = "text/xml; encoding='utf-8'";
//"application/x-www-form-urlencoded";
httpWReq.ContentLength = data.Length;
using (Stream stream = httpWReq.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
System.Windows.Forms.MessageBox.Show(responseString);
}
catch (System.Exception excep)
{
System.Windows.Forms.MessageBox.Show(excep.Message);
}
ActionController::StrongParameters#params is very different from ActionDispatch::Request#body. These two methods serve different purposes.
Check out Chapter 4: Parameters in the Action Controller Overview to learn more.

How to multipart post form data to LinkedIn using OAuth 1 and DotNetOpenAuth?

I'm using the DotNetOpenAuth framework which has been great to get up to speed with consuming data.
I'm using it to talk to LinkedIn and am having trouble figuring out the correct approach to posting/sharing information to the site. Here is the reference I am using - http://developer.linkedin.com/documents/share-api
When I execute the below code I always get the below error responses;
Error occurred while sending a direct message or getting the response.
The remote server returned an error: (400) Bad Request.
I am using Oauth v1.0a.
Here is my code;
try
{
HttpDeliveryMethods resourceHttpMethod = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><share><comment>83% of employers will use social media to hire: 78% LinkedIn, 55% Facebook, 45% Twitter [SF Biz Times] http://bit.ly/cCpeOD</comment>";
xml += "<content><title>Survey: Social networks top hiring tool - San Francisco Business Times</title>";
xml += "<submitted-url>http://sanfrancisco.bizjournals.com/sanfrancisco/stories/2010/06/28/daily34.html</submitted-url>";
xml += "<submitted-image-url>http://images.bizjournals.com/travel/cityscapes/thumbs/sm_sanfrancisco.jpg</submitted-image-url>";
xml += "</content><visibility><code>anyone</code></visibility></share>";
var multiparts = new List<MultipartPostPart>();
MultipartPostPart part = MultipartPostPart.CreateFormPart("body", xml);
part.PartHeaders[HttpRequestHeader.ContentType] = "application/xml";
multiparts.Add(part);
var resourceEndpoint = new MessageReceivingEndpoint("http://api.linkedin.com/v1/people/~/shares", resourceHttpMethod);
HttpWebRequest request = consumer.PrepareAuthorizedRequest(resourceEndpoint, accessToken, multiparts);
request.ServicePoint.Expect100Continue = false;
IncomingWebResponse response = consumer.Channel.WebRequestHandler.GetResponse(request);
this.resultsBox.Text = response.GetResponseReader().ReadToEnd();
}
catch (Exception ex)
{
}
Thanks
Forgot to write back on this, talking to someone from a vintage google newsgroup I got the direction I needed but wanted to verify the solution before posting.
The big thing I was screwing up on was adding the multipart data prior to sending the request data as opposed to constructing the request myself and writing the new content to the stream.
I'm new to using OAuth and REST so I don't know all the ins and outs, suffice to say I've validated this code against both the LinkedIn and Twitter REST APIs.
Here is the new CODE;
try
{
Encoding encoder = Encoding.ASCII;
HttpDeliveryMethods resourceHttpMethod = HttpDeliveryMethods.PostRequest | HttpDeliveryMethods.AuthorizationHeaderRequest;
byte[] bytes = encoder.GetBytes(xd.OuterXml.ToString());
var resourceEndpoint = new MessageReceivingEndpoint(ResourceURL, resourceHttpMethod);
HttpWebRequest request = _consumer.PrepareAuthorizedRequest(resourceEndpoint, _manager.AccessToken);
request.ServicePoint.Expect100Continue = false;
request.Method = "POST";
request.ContentLength = bytes.Length;
request.ContentType = "application/xml";
using (System.IO.Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
IncomingWebResponse response = _consumer.Channel.WebRequestHandler.GetResponse(request);
ret = true;
}
catch (Exception ex)
{
_Logger.Error(OpenLogger.FormatException(ex));
}

How to remove an attachment from Jira 4.4 using Http

I have been looking for a way to remove an attachment from Jira using the SOAP Api, but it seems that this is not possible natively, and I would prefer not having to implement a new plugin for Jira, as suggested in the accepted answer to this question, or recompiling the existing plugin to support this as mentioned here.
This answer to the abovementioned question seems to do exactly what I want, but alas, I can't get i to work. The response i get is an error stating that:
XSRF Security Token Missing
JIRA could not complete this action due to a missing form token.
You may have cleared your browser cookies, which could have resulted in the expiry of your current form token. A new form token has been reissued.
As I am using Asp.Net MVC C#, I have used the code from the answer, as is, with only the server url adjusted, as well as with different credentials (a Jira user) and the username/password passed through as request parameters using:
os_username=jirausername&os_password=xxxxxxx
The code I am currently using is as follows:
public void RemoveAttachment(string issueid, string attachmentid)
{
using (System.Net.WebClient client = new System.Net.WebClient())
{
//Compute jira server base url from WS url
string baseUrl = _service.Url.Substring(0, _service.Url.IndexOf("/rpc/"));
//Compute complete attachment url
string attachmenturl = baseUrl + "/secure/DeleteAttachment.jspa?id=" +
issueid + "&deleteAttachmentId=" + attachmentid;
client.Credentials = new System.Net.NetworkCredential("jirausername", "xxxxxxx");
string response = client.DownloadString(attachmenturl);
}
}
I ended up using a method that first requests the deletion confirmation form, then extracts a required token from the form, and finally posts something equivalent to the form content in order to delete the attachment. Code below.
public void RemoveAttachment(string issueid, string attachmentid)
{
//Compute jira server base url from WS url
string baseUrl = _service.Url.Substring(0, _service.Url.IndexOf("/rpc/"));
//Compute complete attachment deletion confirm url
string confirmurl = baseUrl + "/secure/DeleteAttachment!default.jspa?id=" +
issueid + "&deleteAttachmentId=" + attachmentid + "&os_username=jirauser&os_password=xxxxxx";
//Create a cookie container to maintain the xsrf security token cookie.
CookieContainer jiracontainer = new CookieContainer();
//Create a get request for the page containing the delete confirmation.
HttpWebRequest confirmrequest = (HttpWebRequest)WebRequest.Create(confirmurl);
confirmrequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
confirmrequest.CookieContainer = jiracontainer;
//Get the response and the responsestream.
WebResponse confirmdeleteresponse = confirmrequest.GetResponse();
Stream ReceiveStream = confirmdeleteresponse.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader confirmreader = new StreamReader(ReceiveStream);
// Read the content.
string confirmresponse = confirmreader.ReadToEnd();
//Create a regex to extract the atl/xsrf token from a hidden field. (Might be nicer to read it from a cookie, which should also be possible).
Regex atl_token_matcher = new Regex("<input[^>]*id=\"atl_token\"[^>]*value=\"(?<token>\\S+)\"[^>]*>", RegexOptions.Singleline);
Match token_match = atl_token_matcher.Match(confirmresponse);
if (token_match.Success)
{
//If we found the token get the value.
string token = token_match.Groups["token"].Value;
//Compute attachment delete url.
string deleteurl = baseUrl + "/secure/DeleteAttachment.jspa";
//Construct form data.
string postdata = "atl_token=" + HttpContext.Current.Server.UrlEncode(token) + "&id=" + issueid + "&deleteAttachmentId=" + attachmentid + "&Delete=Delete&os_username=jirauser&os_password=xxxxxx";
//Create a post request for the deletion page.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(deleteurl);
request.KeepAlive = false;
request.CookieContainer = jiracontainer; // Remember to set the cookiecontainer.
request.ProtocolVersion = HttpVersion.Version10;
request.Method = "POST";
//Turn our request string into a byte stream
byte[] postBytes = Encoding.ASCII.GetBytes(postdata);
//Make sure you specify the proper type.
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postBytes.Length;
Stream requestStream = request.GetRequestStream();
//Send the post.
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
//Get the response.
WebResponse deleteresponse = request.GetResponse();
// Open the responsestream using a StreamReader for easy access.
StreamReader deleteresponsereader = new StreamReader(deleteresponse.GetResponseStream());
// Read the content.
string deleteresponsecontent = deleteresponsereader.ReadToEnd();
// do whatever validation/reporting with the response...
}
else
{
//We couldn't find the atl_token. Throw an error or something...
}
}
Edit:
Same thing works for removing comments. Replace 'attachment' with 'comment' and 'deleteAttachmentId' with 'commentId' and you should be good to go.

Resources