I'm trying to create an Atompub service with ASP.NET WEB API, all it's ok but when I try to post any image from Windows Live Writer I get an error "The blog doesn't allow the image load" I'm reading the ietf doc.
My services controller code:
public class ServicesController : ApiController
{
public HttpResponseMessage Get()
{
var serviceDocument = new ServiceDocument();
var workSpace = new Workspace
{
Title = new TextSyndicationContent("Nicoloco Site"),
BaseUri = new Uri(Request.RequestUri.GetLeftPart(UriPartial.Authority))
};
var posts = new ResourceCollectionInfo("Nicoloco Blog",
new Uri(Url.Link("DefaultApi", new { controller = "blogapi" })));
posts.Accepts.Add("application/atom+xml;type=entry");
var images = new ResourceCollectionInfo("Images Blog",
new Uri(Url.Link("DefaultApi", new { controller = "images" })));
images.Accepts.Add("image/png");
images.Accepts.Add("image/jpeg");
images.Accepts.Add("image/jpg");
images.Accepts.Add("image/gif");
var categoriesUri = new Uri(Url.Link("DefaultApi", new { controller = "tags", format = "atomcat" }));
var categories = new ReferencedCategoriesDocument(categoriesUri);
posts.Categories.Add(categories);
workSpace.Collections.Add(posts);
workSpace.Collections.Add(images);
serviceDocument.Workspaces.Add(workSpace);
var response = new HttpResponseMessage(HttpStatusCode.OK);
var formatter = new AtomPub10ServiceDocumentFormatter(serviceDocument);
var stream = new MemoryStream();
using (var writer = XmlWriter.Create(stream))
{
formatter.WriteTo(writer);
}
stream.Position = 0;
var content = new StreamContent(stream);
response.Content = content;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/atomsvc+xml");
return response;
}
}
The http GET Request generate the follow XML:
<?xml version="1.0" encoding="utf-8"?>
<app:service
xmlns:a10="http://www.w3.org/2005/Atom"
xmlns:app="http://www.w3.org/2007/app">
<app:workspace xml:base="http://localhost:53644/">
<a10:title type="text">Nicoloco Site</a10:title>
<app:collection href="http://localhost:53644/api/blogapi">
<a10:title type="text">Nicoloco Blog</a10:title>
<app:accept>application/atom+xml;type=entry</app:accept>
<app:categories href="http://localhost:53644/api/tags?format=atomcat" />
</app:collection>
<app:collection href="http://localhost:53644/api/images">
<a10:title type="text">Images Blog</a10:title>
<app:accept>image/png</app:accept>
<app:accept>image/jpeg</app:accept>
<app:accept>image/jpg</app:accept>
<app:accept>image/gif</app:accept>
</app:collection>
</app:workspace>
</app:service>
But I can't publish images using this service.
Best regards.
I found my error on "categories line", WLW log file shows a malformed XML error in this line, I removed it and all works fine for me... in this blog post explains how WLW Works with image files
If somebody have any comment... I'll be grateful
Related
This is a followup to my previous question: Xamarin.Forms App return data to calling App
That works perfectly and I can share images to anywhere, except to Facebook comments. When I click the camera on the content box the app can be selected, I can select the image, Set result and Finish are called, and the app closes and it sends data to Facebook, and then however I then get the error : The image could not be uploaded, try again?
I can't find any fundamental differences between posting to a status or a comment, so I'm guessing it's subtle. Any thoughts on how I can change my intent to post properly?
Adding for completeness:
Bitmap b = null;
string url;
if (!string.IsNullOrEmpty(this.saleItems[i].ImageUrl))
{
url = this.saleItems[i].ImageUrl;
}
else
{
url = await FileHelper.GetLocalFilePathAsync(this.saleItems[i].Id);
}
//download
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
b = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
//set local path
var tempFilename = "test.png";
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, tempFilename);
using (var os = new FileStream(filePath, FileMode.Create))
{
b.Compress(Bitmap.CompressFormat.Png, 100, os);
}
b.Dispose();
var imageUri = Android.Net.Uri.Parse($"file://{sdCardPath}/{tempFilename}");
var sharingIntent = new Intent();
sharingIntent.SetAction(Intent.ActionSend);
sharingIntent.SetType("image/*");
sharingIntent.PutExtra(Intent.ExtraText, "some txt content");
sharingIntent.PutExtra(Intent.ExtraStream, imageUri);
sharingIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
//await SaleItemDataService.Instance.BuySaleItemAsync(this.saleItem);
SetResult(Result.Ok, sharingIntent);
Finish();
Use below:
Intent sharingIntent = new Intent();
string imageUri = "file://" + requestedUri;
sharingIntent.SetData(Android.Net.Uri.Parse(imageUri));
This is an error thrown in botframework dashboard (issues).
{"error":{"message":"(#100) Failed to fetch the file from the url","type":"OAuthException","code":100,"error_subcode":2018008,"fbtrace_id":"CyiaDTS8Rjz"}}
This happens when i try to post videoCard.
My code :
resultMessage.AttachmentLayout = AttachmentLayoutTypes.Carousel;
resultMessage.Attachments = new List<Attachment>();
VideoCard video = new VideoCard()
{
Title = "title",
Media = getMedia(activities[counter]),
};
resultMessage.Attachments.Add(video.ToAttachment());
and getMedia function :
public IList<MediaUrl> getMedia (ActivityModel model)
{
IList<MediaUrl> mediaUrl = new List<MediaUrl>();
MediaUrl item = new MediaUrl();
item.Url = model.DocumentPath;
mediaUrl.Add(item);
return mediaUrl;
}
model.Document path is simple youtube video ...
Any idea ?
i would like to reconstruction my last project.
in past, i did't use any Web API.
can i just use the ODataQueryOptions to do $filter, $orderby , $top ,$skip
for my query in my own handler.ashx ?
some thing like.
var option = new ODataQueryOptions(request.params);
var query = option.ApplyTo(db.products);
Based on sfuqua's answer above I made my own helper class that builds OdataQueryOptions class based on Odata Uri:
using System.Linq;
using System.Net.Http;
using System.Web.Http.OData;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Query;
namespace OdataHelpers
{
public static class ODataBuilder<T>
{
public static ODataQueryOptions<T> BuildOptions(string oDataUri)
{
var baseUri = "";
var odUri = "";
var spl = oDataUri.Split('?');
if (spl.Count() == 0)
odUri = spl[0];
else
{
baseUri = spl[0];
odUri = spl[1];
}
if (string.IsNullOrEmpty(baseUri))
baseUri = "http://localhost/api/" + typeof(T).Name;
var request = new HttpRequestMessage(HttpMethod.Get, baseUri + "?" + oDataUri.Replace("?", ""));
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.AddEntity(typeof(T));
var edmModel = modelBuilder.GetEdmModel();
var oDataQueryContext = new ODataQueryContext(edmModel, typeof(T));
return new ODataQueryOptions<T>(oDataQueryContext, request);
}
}
}
Example use:
var OdataStuff = ODataBuilder<CustomerIntView>.BuildOptions("$orderby=Id");
One way to accomplish this is by manually constructing the request URI and setting that in the request parameter of the ODataQueryOptions constructor. So this may not be precisely what the original poster was looking for (question needed some clarification).
In my case I have a unit test, and I wanted to validate that the odata options were being applied to my queryable object. In the following sample code, assume that you are testing a ProductController that has a ProductName field in it.
// Manually set an OData query parameter
const string restUrl = "http://localhost/api/product?$orderby=ProductName";
// Need to construct an HTTP Context and a Request, then inject them into the controller
var config = new HttpConfiguration();
var request = new HttpRequestMessage(HttpMethod.Post, restUrl);
var route = config.Routes.MapHttpRoute(WebApiConfig.DefaultRouteName, "api/{controller}/{id}");
var routeData = new HttpRouteData(route, new HttpRouteValueDictionary { { "controller", "Product" } });
var controller = new ProductController()
{
Request = request,
ControllerContext = new HttpControllerContext(config, routeData, request),
Url = new UrlHelper(request)
};
// Build up the OData query parameters
var modelBuilder = new ODataConventionModelBuilder();
modelBuilder.AddEntity(typeof(Product));
var edmModel = modelBuilder.GetEdmModel();
var oDataQueryContext = new ODataQueryContext(edmModel, typeof(Product));
var oDataQueryOptions = new ODataQueryOptions<Product>(oDataQueryContext, _controller.Request);
// Finally, call the controller
var result = controller.Get(oDataQueryOptions);
I do think you can if you can constructor an instance of ODataQueryOptions.
But, What's this:
var option = new ODataQueryOptions(request.params);
Web API doesn't provide such constructor. Is it your own implementation?
Thanks.
I am currently in the process of developing a Windows 8 (Windows Store) app that connects to a sharepoint site using the REST interface. Currently, I have successfully managed to pull down list data from the _vti_bin/ListData.svc/ uri. However, I am stuck on creating new list items from within the app, and Posting these back into sharepoint.
I am trying to use an HTTP POST method, however am receiving a 405 error code: MethodNotAllowed. Below is my code:
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.UseDefaultCredentials = true;
HttpClient newClient = new HttpClient(clientHandler);
// HttpResponseMessage response = newClient.PostAsync("http://sharepoint/.../_vti_bin/ListData.svc/Nominations", test);
var resp = await newClient.GetAsync(newUri("http://sharepoint/.../_vti_bin/ListData.svc/Nominations"));
using (newClient)
using (var ms = new MemoryStream())
{
var djs = new DataContractJsonSerializer(typeof(NominationsItem));
djs.WriteObject(ms, test);
ms.Position = 0;
var sc = new StreamContent(ms);
sc.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
resp = test == null
? await newClient.PutAsync(new Uri("http://sharepoint/.../_vti_bin/ListData.svc/Nominations"), sc)
: await newClient.PostAsync(new Uri("http://sharepoint.../_vti_bin/ListData.svc/Nominations"), sc);
resp.EnsureSuccessStatusCode();
}
Any help would be appreciated!
I've verified using System.Text.Encoding.ASCII.GetString(ms.ToArray)); that my memorystream has the expected data.
However using the LinqToCSV nuget library will not generate my csv file. I get no errors or exceptions thrown. I just get an empty file when I'm prompted to open the file.
Here is my Action Method
public FileStreamResult Export(){
var results = _service.GetProperties().Take(3);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
System.IO.TextWriter txt = new System.IO.StreamWriter(ms);
CsvFileDescription inputFileDescription = new CsvFileDescription{
SeparatorChar =',',
FirstLineHasColumnNames = true
}
;
CsvContext csv = new CsvContext();
csv.Write(results,txt,inputFileDescription);
return File(ms , "application/x-excel");
}
I find it interesting, if I change the return type to contentResult, and the return method to Content() and pass it System.Text.Encoding.ASCII.GetString(ms.ToArray)); I do get a browser window showing my data.
Make sure you reset stream position to 0. Also make sure you flush your StreamWriter before that.
Calling the Web API method to return CVS file from JavaScript.
public HttpResponseMessage Bidreport([FromBody]int formData).....
Fill in your IEnumerable<YourObject>query = from LINQ query
....
This is how to return it:
using (var ms = new MemoryStream())
{
using (TextWriter txt = new StreamWriter(ms))
{
var cc = new CsvContext();
cc.Write(query, txt, outputFileDescription);
txt.Flush();
ms.Position = 0;
var fileData = Encoding.ASCII.GetString(ms.ToArray());
var result = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent(fileData)};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-excel");
return result;
}
}