wp-net / wordpresspcl Goto Github PK
View Code? Open in Web Editor NEWThis is a portable library for consuimg the WordPress REST-API in (almost) any C# application
License: MIT License
This is a portable library for consuimg the WordPress REST-API in (almost) any C# application
License: MIT License
One problem I have with the WordPress API is that comments for a post are unordered. This is an issue as comments might be nested so you can't just order them by date.
I think it might make sense to have a helper method in the library sorting the comments by date and also parent, and also adding a "depth" property indicating how many parents a comment actually has. That class should extend the current Comment-Model, and needs a helper method turning the standard response into an ordered one.
https://jacobmartella.com/2016/12/19/displaying-threaded-comments-with-wordpress-rest-api/
What do you guys think?
Hi,
When I use the Create method in order to create a category, the server returns a 201 http status code, but when the response is readed, the content starts with :
< head >< title >Document Moved< /title >< / head>< body >< h1 >Object Moved< / h1 >This document may be found < a HREF="/wp-json/wp/v2/categories/1414">here< / a>< / body >{"id":1414,"count":0,"description":"Description category","link":"htt
So the Deserialize (HttpHelper - Line 92) throws an error.
Has someone already get this issue ?
Hi!
I have a suggestion to create the ability to send unstructured queries. This can be useful when using our plug-in to work not only with the WP REST API Core but also with the REST API plugins. For example, Contact Form 7 has its endpoint, and Woocommerce extends the standard status list (which we have hardcoded in Enums). Thus, we could give the end users of the library the opportunity to send non-standard queries.
Like that:
var obj = new {ID=123, Name=test};
//Get
var responce=client.CustomRequest.Get("http://mysite.com/wp-json/wp/v2/custom",obj,auth);
//Post
var responce=client.CustomRequest.Post("http://mysite.com/wp-json/wp/v2/custom",obj,auth);
//Put
var responce=client.CustomRequest.Put("http://mysite.com/wp-json/wp/v2/custom",obj,auth);
//Delete
var responce=client.CustomRequest.Delete("http://mysite.com/wp-json/wp/v2/custom",obj.ID,auth);
Since most of the work has been done for the big restructuring I started looking at the tests and would like to propose a general structure.
Each of the entity extensions for the client will get it's own test class, so
Posts_Tests.cs
Comments_Tests.cs
Tags_Tests.cs
...
Each test class will contain tests for the CRUD-Implementation plus additional tests that might make sense. Test names will be prefixed by the entity so the list of tests in the Test Explorer is more structured. I also propose to drop the _Tests suffix as they seem unnecessary to me.
So each test class will have at least these methods
[TestMethod]
Posts_Create()
Posts_Read()
Posts_Read_Single() // not sure about the naming, maybe Posts_Read_ByID?
Posts_Update()
Posts_Delete()
Thoughts?
I'm getting token valid
var isValidToken = await client.IsValidJWToken();
But when I create something, I got nothing
var user = new User();
user.FirstName = "The Mail";
user.UserName = "themail";
user.Password = "123@abc";
user.Email = "[email protected]";
client.Users.Create(user);
What am I missing?
Is it possible submit a new meta tag in the moment that I'm creating the post?
Something like:
List<object> meta = new List<object>();
meta.Add(new KeyValuePair<string, string>("external_post_id", "9999"));
first.Meta = meta;
return await client.Posts.Update(first);
I've been having mixed success getting responses from my local WordPress installation.
I do some processing on posts as they when they come in and require the use of the edit context. However when I add query.Context = Context.Edit, the response is NULL when it returns from Posts.Query(query).
The relevant lines are:
Dim query = New Utility.PostsQueryBuilder
query.Page = page
query.After = time
query.PerPage = _webConfigHelper.Get("jsonPostsPerPage")
query.OrderBy = PostsOrderBy.Modified
query.Order = Order.ASC
query.Embed = True
query.Context = Context.Edit
_wordpressClient.AuthMethod = AuthMethod.JWT
Await _wordpressClient.RequestJWToken(_user, _pass)
Dim validToken = Await _wordpressClient.IsValidJWToken()
If validToken Then
Dim response = Await _wordpressClient.Posts.Query(query)
Dim url = query.BuildQueryURL() ' just used to debug
If response IsNot Nothing AndAlso response.Count > 0 Then
Dim rawposts = response.Select(Function(x) ConvertPost(x)).ToList()
Return rawposts
End If
End If
The JWT auth seems to be working as I can examine the token and it is the same one I can use in Postman to get results to the same URL. If i leave out setting the context to edit, I get a response that is not NULL.
Is this a bug, or am I doing something wrong?
I make a web application using WordpressPCL, It's working on my localhost (VS debug). But, When I upload to hosting (plesk panel, Azure), All functions need authorized not working
await client.RequestJWToken(user, pass);
await client.Posts.Create(_post);
I checked with Fiddler, I don't see it call to /wp-json/
I have a suggestion to add to model classes (Post, User,Media etc) constructors with required parameters. Required parameters - fields required to create entity in WP REST API
Example: in WP API for user creation required parameters are: username, email, password. Without this params we cannot create user.
I think that we should block opportunity to send non-complete create request to end users of this library and might help them to understand which parameters are required for request.
But this change has the other side - it breaks DTO pricniple that DTO class must not have any logic in it (I think that simple constructor is an logic). But may be I am wrong and constructor with simple logic that pass input values to thier properties is not logic and not breaks the DTO pricnipe and we can do it simple
Reminder to add documentation for threaded comments ;-)
As @polushinmk suggested we should add an extension method to the comment list to make is easier to turn these into a threaded list.
We've started adding documentation to the Wiki pages, but there's still a lot missing. Feel free to help us adding the missing pieces.
An option to list posts published after a specific date.
I tried udpating yoast meta description field which is called "_yoast_wpseo_metadesc".
However, when I try to update nothing changes.
var metaDescYoast =new { _yoast_wpseo_metadesc = finalWord };
wordpressPost.Meta = new List
{
metaDescYoast
};
var result = client.Posts.Update(wordpressPost).Result;
Ability to call the /users API.
Hi there!
I just looked at the structure of 4 unrealized endpoints: Post revisions, Post types, Post statuses and Taxonomies. All of them do not have a full CRUD structure, but implement only Read operations (Post revision still implement Delete). Implement them using the interface ICRUDOperation does not work, since almost all methods will not be implemented.
I have 2 solutions:
Attention: this will NOT cause a violation of backwards compatibility, so can be used in version 1.1
2. Implement without using interfaces
Suggestions?
hi thx for helpful Library
I can not connect to rest api my web site
worpress version is : 4.8.2
and this link : http://marjafile.com/wp-json/ has exist
i install jwt and enable header and added my token
when i use this code
var client = new WordPressClient("http://marjafile.com/wp-json/"); await client.RequestJWToken("admin", "passadmin"); var posts = await client.Posts.GetAll();
always return 0 post and null
I want to put this up for discussion since in came up here #63 .
When restructuring the library we made it private by default just to be safe. Obviously there could be scenarios where it might make sense to use an existing JWT token to create a custom request outside of this library.
Do you guys have any strong feelings about either side of the argument?
If we decide to do this, we'll should probably expose it though a GetToken()-method (like the logout) since the Token is inside the private _httpHelper property. Right?
Hi, I just noticed that QueryBuilder appends QuestionMark (?) multiple times when multiple properties of the object are set. e.g.
(new QueryBuilder("demo.wp-api.org/wp-json/") {
Page = 2,
Embed = true
}).ToString();
the above code gives http://demo.wp-api.org/wp-json/?page=2?_embed
instead of http://demo.wp-api.org/wp-json/?page=2&_embed
I'd send a pull request, but my last one hasn't been resolved yet. @ThomasPe
Thanks for the Library , but Im very new at both C# and Xamarin Form.
So any github working sample using this Library are very much appreciated.
Thanks!
I successfully receive JWT token. I make good request, I see 201 created using wireshark. I can see that wordpress returns response, however this library gives me null for response: ( I tried creating posts and users)
var response=await client.Posts.Create (post)
Hi guys,
I'm developing on F# but I have also tested my scenarios using the test scripts you have in your repo, both my code and your test cases produce the same results, this way I make sure my code is working as it should based on your test scripts.
My issue is when using the Comments QueryBuilder to fetch comments by Status. This property seems not to be working, it doesn't matter what value I use, Approve/Spam/Pending, result is always null.
Your test script with Statuses added:
`[TestMethod]
public async Task Comments_Query()
{
var client = await ClientHelper.GetAuthenticatedWordPressClient();
var queryBuilder = new CommentsQueryBuilder()
{
Statuses = new CommentStatus[] { CommentStatus.Pending },
Page = 1,
PerPage = 15,
OrderBy = CommentsOrderBy.Id,
Order = Order.DESC
};
var queryresult = await client.Comments.Query(queryBuilder);
Assert.AreEqual(queryBuilder.BuildQueryURL(), "?page=1&per_page=15&orderby=id&order=desc");
Assert.IsNotNull(queryresult);
Assert.AreNotSame(queryresult.Count(), 0);
}`
My code:
`member this.getProductComments () =
async {
let! client = this.getWordPressAuthenticatedConnection()
let query = CommentsQueryBuilder()
//query.AuthorEmail <- ""
query.Statuses <- [|CommentStatus.Pending|]
let queryString = query.BuildQueryURL()
let! comments = client.Comments.Query(query, true) |> Async.AwaitTask
//let! comments = client.Comments.GetAll() |> Async.AwaitTask // This works for all approved
return comments
}`
For Spam comments I use Akismet, and for Pending comments I tried importing some comments in Draft status and approving already approved comments (existing comments and also comments created through your test scripts).
Thanks!
Victor
I've started adding XML comments to public types or members (see Models/Post.cs), but there are still a lot of comments missing.
The idea is to copy the summary & remarks from the official docs to have them available in IntelliSense. Any help is appreciated!
I see there isnt a method to do that. The proper way to do something like this is first to list all posts and then to get the categories from the posts?
Hi,
Not sure if this issue is related to WordPressPCL or to the WordPress API that won't allow to approve a comment from your library.
I'm running the following code:
comment.Status <- CommentStatus.Approve; x.UpdateComment(comment)
If I do the same but changing some other properties as the content of the comment or the author or some other properties, it just works fine.
Do you know if approving a comment can be done this way or if it's even possible through WordPressPCL library?
Thanks,
Victor
Hello!
I think that using the library in this form:
Wordpressclient.Posts instead of wordpressclient.ListPosts ()
Wordpressclient.Posts.GetByXXX ()
Wordpressclient.Posts.Create (Post post)
Wordpressclient.Posts.Update (Post post)
Wordpressclient.Posts.Delete ()
More convenient and understandable than wordpressclient.ListPosts (), wordpressclient.CreatePost, wordpress.UpdatePost
Same for Comments, Categories and other
To do this, you need to create a group of classes, such as PostsOperations, CommentsOperations, CategoriesOperations, and others, which you can inherit from the
ICRUDOperation <T>
interface that will declare all common methods such as Create (T item), Update (T Item), Delete (T item)
In the main class, it will be necessary to create several properties that will grant access to these classes.
If this is interesting, then I can create a pull request with the code to show how the Posts object looks like after this
I'm using ACFs (Advanced Custom Fields), they are returned as node "acf" when the appropriate plugin (https://github.com/airesvsg/acf-to-rest-api/) is enabled, example:
...,
"acf": {
"projectyear": "2017",
"projectowner": "wp-net"
},
When creating new post they need to be send as "fields" node, example:
...,
"fields": {
"projectowner": "wp-net"
},
Code can be found under pull requst #9.
Hi there!
According to #23 we already have implementation of List Categories but only in reorg-methods brunch
I think that we should create a roadmap/todo of new release.
TODO:
PP to version 1.1:
whenever i try to get all posts returns 0 i tried requests on ISS and Linux servers and response still 0, any idea ?
-Xamarin Android
-VS 2017
and tried with https://github.com/z-ji/WordPressPCL/ and works fine but has issues wit ISS and HTTPS
I think it would make sense to reintroduce the .Get-Methods to quickly get Posts, Pages etc. with default values. So await client.Posts.Get(bool embed) will simply return the 10 latest posts. For everything more sophisticated we already have our new QueryBuilder.
Thoughts?
In wordpress you can set up menus. Is there a way to get the menu data?
I have a suggestion of rewrite the QueryBuilder.
Example of my vision of it:
IEnumerable<Post> queryResult=client.Posts.Query()
.With(PostQueryEnum.PerPage,20)
.With(PostQueryEnum.Author,11)
.OrderBy(OrderBy.Date,Order.ASC)
.Result();
So the main idea is make a query like a pipeline with some common methods:
It will be 1 querybuilder for 1 client type. Posts - PostsQueryBuilder, Comments - CommentsQueryBuilder etc
To limit possible filter values I suggest to create Enums like PostQueryEnum with predefined variables like:
enum PostQueryEnum{
Author,
PerPage,
Page,
etc
}
I have a working prototype of this QueryBuilder working to query Posts.
Some questions:
Dictionary<PostQueryEnum,object> parameters = new Dictionary<PostQueryEnum,object>(){
new KeyValuePair(PostQueryEnum.PerPage,20),
new KeyValuePair(PostQueryEnum.Author,1)
}
client.Posts.Query().With(parameters).Result();
or like this
client.Posts.Query().With((PostQueryEnum.Author,1),(PostQueryEnum.PerPage,20)).Result();
Should we do that and which variant more convinient to use?
Looking for your reviews and comments!
I'm trying create new post, but sometimes It return null
string _path = HttpContext.Current.Server.MapPath(post.THUMBNAIL);
string extension = Path.GetExtension(_path);
string _imagename = HelperExtensions.ConvertSlug(post.TITLE);
var thumbnail = await client.Media.Create(_path, _imagename + extension);
Post _post = new WordPressPCL.Models.Post
{
Title = new Title(post.TITLE),
Content = new Content(post.CONTENT),
Categories = new int[] { cat.CAT_ID.Value },
Excerpt = new Excerpt(post.SHORT_CONTENT),
Status = Status.Publish,
Date = DateTime.Now
};
if (thumbnail != null)
_post.FeaturedMedia = thumbnail.Id;
var posted = await client.Posts.Create(_post);
How do I read/get settings in code
Hi to all.
I wondered if anyone had already used the library in a xamarin forms project.
Thank you
Hi,
The wordpress client constructor seems to be appending "/wp-json/" to the uri when it doesn't end with it.
This prevents the possibility to use WordPressPCL on Blogs hosted on wordpress.com, for their Rest Api Url is like https://public-api.wordpress.com/wp/v2/sites/{name_of_the_site}.wordpress.com/
I', trying to use this lib. But, I get probem
client = new WordPressClient("http://duhoc.thaison.top/wp-json") { AuthMethod = AuthMethod.JWT }; await client.RequestJWToken("username", "password"); var IsValidToken = await client.IsValidJWToken();
IsValidToken always return false.
I am trying to delete posts. I get response: 405 method not allowed.
I tried configuring IIS with this:
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/> <!-- ADD THIS -->
</modules>
... rest of settings here
I am not sure is there anything related to this library or to IIS configuration. Do you have IIS configuration that works. Obvoiosly tests passed, so it seems DELETE requests can work. POST and GET requests are working correctly.
Hi there!
Now I will offend at WP REST API Media endpoint and json schema.
And some fun with content-disposition header (info about this not included in official docs)
https://wordpress.stackexchange.com/questions/209928/add-media-with-wp-rest-api-v2
Firstly, let me start by stating that I'm not familiar with the WordPress API, or WordpressPCL.
Secondly thank for a potentially great starting point for interacting with WordPress!
I have an integration project I'm working on and started with the WordPressPCL nuget package in my project (a WinForms application), and then subsequently downloaded the git repo and managed to get the WordPressClient source running under Visual Studio 2015.
I had to do this because, the NuGet package when used with my WordPress installation (WordPress 4.8.1) seems to only be returning the admin users when calling Users.GetAll:
var _wordPressUsers = (List<WordPressPCL.Models.User>) await _wordPressClient.Users.GetAll();
As a starting point, I modified the call to use authorization (as I realised that's going to make the difference), so changed the call to:
var _wordPressUsers = (List<WordPressPCL.Models.User>) await _wordPressClient.Users.GetAll(false, true);
..and the situation became worse as now nothing was returned. Checking through the source code at the point:
var responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
...the response string contains the site home page HTML and not a JSON object as expected (although the response code was 200).
Following that, I thought I'd check to see if this was a problem with the Wordpress API by logging into Wordpress as the API user (using FireFox), and browsing to the API endpoint:
MyWebsite.com/wp-json/wp/v2/users?per_page=100&page=1
...sure enough, I only get 4 users (out of 117, incidentally all of these 4 being the admin users). Then I checked the request headers under FireFox and realized it was missing the authentication header, so modified the header using the token used by the WordPressClient:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9iZW5jaG1hcmttaW5lcmFscy5jb20iLCJpYXQiOjE1MDUxMjY4MjQsIm5iZiI6MTUwNTEyNjgyNCwiZXhwIjoxNTA1NzMxNjI0LCJkYXRhIjp7InVzZXIiOnsiaWQiOiIxMTMifX19.431EpDbFoEBI8isfbSHFdkboHLqt3jxlY2BOwEzUUak
Low and behold, the first 100 users of 117 were returned.
Experimenting a bit more, I removed the Cookies header from the browser, and I then get the original behaviour when Authorization is enabled, as I'm re-directed to the Home Page (checking the network traffic this is preceeded by a 302 redirect).
Which doesn't sound right. So I'm obviously doing something wrong.
Source I'm using:
_wordPressClient = new WordPressClient(_wpBaseUrl);
_wordPressClient.AuthMethod = AuthMethod.JWT;
await _wordPressClient.RequestJWToken(_wpUser, _wpAuth);
if (await _wordPressClient.IsValidJWToken()) {
var _wordPressUsers = (List<WordPressPCL.Models.User>) await _wordPressClient.Users.GetAll(false, true);
}
Should the client/API require a cookie collection in order for this to work?
Or have I missed something fundamental?
Due to #71 we should allow library users to cnahge default deserialization settings by passing it to HttpHelper class (like HttpPreProcessing).
It could be usefull if WP site uses non standard datetime format.
I will prepare PR later. Plz assign to me
As far as I can tell there's currently no way log a user out (so forgetting the JWT token). We should add this.
Currently every size version inside a Media-Object (thumbnail, full etc.) has it's own class, which is impractical since plugins, themes etc can add different sizes with different names.
That's why I propose to change the Size class into a Dictionary<string, MediaSize> so you can access all versions by using the size-name as a string, like this:
Media.MediaDetails.Sizes["Thumbnail"] instead of Media.MediaDetails.Sizes.Thumbnail
Thoughts?
When building a UWP App setting the Min version to Fall Creators Update 16299 the library will return null for all GetPosts-Calls (haven't tried others yet).
Setting Target version to Fall Creators update and Min Version to Creators Update 15603 works.
Hi!
I think that library code is stable and ready for production use, so it is possible to add info about lib to official WP REST API Handbook.
https://developer.wordpress.org/rest-api/using-the-rest-api/client-libraries/
But I can`t find anyone from WP to write about this on this page.
Hello,
The package for this project on Nuget does not contain ListPostsBySearch ...
Hi!
Some time ago I found on the Internet a link to the plug-in for Visual Studio Async Fixer https://visualstudiogallery.msdn.microsoft.com/03448836-db42-46b3-a5c7-5fc5d36a8308_blank. This plugin analyzes the use of async / await in the code and suggests correcting its incorrect use. At us, according to a plug-in, about 30 incorrect calls async await (AsyncFixer01) which are not necessary, but thus it is generated overhead code.
I decided to run tests using BenchmarkDotNet.
The Categories.Query () method was called 25 times with parameters of 100 categories per page
The results in the tables below:
Using Async / await
BenchmarkDotNet=v0.10.9, OS=Windows 7 SP1 (6.1.7601)
Processor=Intel Xeon CPU X5675 3.07GHz, ProcessorCount=4
Frequency=14318180 Hz, Resolution=69.8413 ns, Timer=HPET
.NET Core SDK=2.0.0
[Host] : .NET Core 2.0.0 (Framework 4.6.00001.0), 64bit RyuJIT
Job-CVVEAN : .NET Core 2.0.0 (Framework 4.6.00001.0), 64bit RyuJIT
LaunchCount=1 RunStrategy=Monitoring TargetCount=25
WarmupCount=5
Method | Mean | Error | StdDev | Min | Max |
---|---|---|---|---|---|
GetCategories | 1.274 s | 0.1699 s | 0.2268 s | 1.112 s | 2.249 s |
Without using async / await
BenchmarkDotNet=v0.10.9, OS=Windows 7 SP1 (6.1.7601)
Processor=Intel Xeon CPU X5675 3.07GHz, ProcessorCount=4
Frequency=14318180 Hz, Resolution=69.8413 ns, Timer=HPET
.NET Core SDK=2.0.0
[Host] : .NET Core 2.0.0 (Framework 4.6.00001.0), 64bit RyuJIT
Job-QRTQAA : .NET Core 2.0.0 (Framework 4.6.00001.0), 64bit RyuJIT
LaunchCount=1 RunStrategy=Monitoring TargetCount=25
WarmupCount=5
Method | Mean | Error | StdDev | Min | Max |
---|---|---|---|---|---|
GetCategories | 1.337 s | 0.1493 s | 0.1993 s | 1.095 s | 1.929 s |
That is, there is a gain in performance, but it is very small. In a real application, the benefit is likely to be quite insensitive, but overall, it cleans up the code a little.
What do you think, can be applied recommendations?
In milestone 1.2 a function was introduced to return the comments in a threaded order including the depth of each comment. ATM this will always show the oldest comments first.
We should introduce a parameter to get the Comments in reverse order (while maintaining the correct order in the comment replies, so just reversing the list won't suffice).
hello, it is possibile EDIT exists post?
var client = new WordPressClient("mysite.com/wp-json");
client.Username = "user";
client.Password = "password";
var postbyid = await client.GetPost(id);
postbyid.Content.Raw = "Edit content";
And Save?
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.