Ruhrpottpatriot.7293:

This is the official topic on GW2.NET. Here you will find firsthand information about the library, ways to obtain it for use and information about development

What is GW2.NET?
At first GW2.NET was a simple wrapper around the public GW2 API that helped the user with transforming the response into well written C# and .NET code. Since then it has eveloved in many ways. Now it is the most complete wrapper built on the .NET Framework featuring a consitent and easy to use method to fetch data from the API itseld.

Features

  • Unified query syntax for each API endpoint
  • Every v1/ endpoint is available
  • Every unauthorized v2/ endpoint.
  • Tile & Render Services support
  • Mumble Support
  • Full async support!

Obtaining GW2.NET
The easiest way of obtaining a working copy of the code is via NuGet. Open the Package Manger Console and type:


Install-Package GW2.NET

Other ways to obtain the code can be found on the documentation page

I’m clueless and don’t know how to start aká Quickstart
Using the library is really simple. At first you have to reference the following GW2.NET libraries:

  • GW2NET.dll
  • GW2NET.Core.dll

If you are using NuGet those references are automatically added for you, no additional work needed.

After that you have to import the namespace


    using GW2NET;

At last you can use the facade class which manages the most common features for you. Below is an example how to get some Quaggans IDs.


    var service = GW2.V2;
    ICollection<string> keys = service.Discover();
    Task<Collection<string>> keysAsync = service.DiscoverAsync(); // Do everything asynchronously.

If you still have questions you can always look at the Documentation. If you still don’t know what you have to do, you can also ask a question in this thread or (better) in the Discussions

I don’t like the way you have done x/y. You suck and I’m sure I can do it better!
Laugh If you think so go ahead, nobody is stopping you! After all the libary is completely open source. Check out our License and code away. If you think you’ve developed a great feature that should be added to the main library simply supply a patch at the Source Code Tab. We will definetly look into it!

Where to go from here?
Recently ArenaNet has opened up some more API endpoints in the v2/ namespace and those need to be included. The next big milestone however is the authorized API that is currently been worked on. We are as eager as you are to the idea to query a characters bank or his skills from outside the game.

How can I contact you?
The simplest way to contact us is right here in the forum. If you want to get sure your question, request or criticism is not lost between other posts, the best option is the Discussions section on Codeplex. You can also contact me via Codeplex directly I also have a Stackoverflow Account. Of course I am not the only one working on the project. There is a whole team behind me who have all done an excellent job of improving every aspect of the code. Onne big Thanks! goes directly to Steven Liekens who made the currently layout possible. Thanks Steven!

Varonth.5830:

.NET 4.5 can handle JSON: http://msdn.microsoft.com/en-us/library/bb410770.aspx

SSL connections are available for basically any language you want:
http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

So I don’t know what exactly you need.

Ruhrpottpatriot.7293:

No my aims was not to provide a json serializer (I’d rather not use 4.5 because 4.5 does not support XP anymore and most users are still using XP and the whole data contract thing is more than just basic) or SSL connections, but a class library which provides developers who write .Net Applications with classes and methods to develop their program more easily.
Think of it as a wrapper around the GW2 API for .NET

kousei.5914:

I’ve started one for my own purposes but I don’t have a problem splitting off the API Wrapper pieces and dropping them on CodePlex if I can get some help maintaining it.

Ruhrpottpatriot.7293:

Sounds great. I’ll do some things on the codeplex site today and tomorrow and publish the thing as soon as possible.

Ok, I’m done with the codeplex page (can be found here: https://gw2dotnet.codeplex.com/). The code is pretty basic and rudimentary as I didn’t have much time and I’m fairly new to the whole WebRequest thing. I’m willing to learn though and I hope to do so by providing to this project.

Remfin.4892:

I’d be happy to give you what I have so far, although it’s not much more but a little more structure and models around the API.

If I could make a suggestion…use HttpClient instead of WebRequests, it’s supposedly much better (it’s also much easier to use).

Ruhrpottpatriot.7293:

Yeah I hope to clean up the code a little bit and write some more basic wrapper methods which just return the JSON Data as .NET objects. Will see if I Get to that later.

Also, if you have a codeplex account (or Microsoft account) pm it to me so I can add you to the team.

Rohan.1403:

I have been working on my own implementation here. Just learned that RestSharp exists so I will see about switching to that tomorrow.

Ruhrpottpatriot.7293:

I’ll look into RestSharp myself and if it offers the functionality wee need I’ll include it in the project.

poke.3712:

I’ve created an example using RestSharp, if anyone is interested: https://gist.github.com/poke/5627036

Killer Rhino.6794:

I’ve created an example using RestSharp, if anyone is interested: https://gist.github.com/poke/5627036

Thanks for sharing, poke! Awesome work.

Ruhrpottpatriot.7293:

Yeah, thanks for the example I’m currently including it in the codeplex project.

Gilosean.3805:

Awesome! The API is really exciting news, and I’m so happy to see that people are already doing stuff in C# with it. Anyone thinking about using Mono/Xamarin to get an Android app out of this?

Some people are setting up a GW2 Trello board and chat room to help coordinate development. The thread is here if you’re interested: https://forum-en.guildwars2.com/forum/community/api/Want-to-collaborate-on-GW2-apps-Start-here/first

Ruhrpottpatriot.7293:

Ok, I included a call with Rest# to the project (much faster thanks for the tip) and added equality comparison and hash code to the event, world and map models.

Still need help with caching though.

Ruhrpottpatriot.7293:

Awesome! The API is really exciting news, and I’m so happy to see that people are already doing stuff in C# with it. Anyone thinking about using Mono/Xamarin to get an Android app out of this?

As this is library is coded purely in .NET and will not include any UI stuff it should be pretty safe to use this with mono (I don’t have any experience with mono however). Still looking for more developers though. Everyone who wants to contribute can PM me here with their Codeplex/MS username and I’ll add him to the developer list.

Ruhrpottpatriot.7293:

Ok, quick heads up.
Implementation runs fine. We are debating some internal issue (for those who want to help and participate: https://gw2dotnet.codeplex.com/discussions/444658) but apart from that we are doing good.

I welcome any input here, but I request that “bigger” topics be discussed on the codeplex site where we have a dedicated discussion section for that.

See you

Thurfir.6381:

Hi everyone, mostly out of curiosity, why do you require a plugin to perform the task? I understand that the 4.5 framework isn’t suitable for everyone, but to my experience the DataContractJsonSerializer is available in .NET 3.5 too, I used it to seralize in some of my projects ;-).

http://msdn.microsoft.com/en-us/library/bb412179%28v=vs.90%29.aspx
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.readobject%28v=vs.90%29.aspx

Have fun!

Rawrfaec.6412:

I don’t know the reason in this case but .NET SDK JSON serializers are relatively slow compared to third party alternatives.

poke.3712:

Hi everyone, mostly out of curiosity, why do you require a plugin to perform the task?

I assume you mean RestSharp? The reason is simply to not re-invent the wheel. The RestSharp library (not a plugin) makes using REST resources very simple and consistent. And especially later when the API is expanded and adds some authentication mechanism, you can just configure RestSharp once to use it and you’re done.

Of course you can write it all in standard .NET framework code—RestSharp is written like that too after all—but you can save quite a bit of work by reusing working and tested libraries.

Thurfir.6381:

Thanx ;-) . I had some bad experiences with some plugins which became more of an hindrance than an actual help, is why I tend to either use the built-in functionnalities, or well-tried plugins only.

About the .NET serializer, If I remember correctly that one is the one used by the WCF Web services, so I genuinely hope the performance difference isn’t that bad xD .

Ruhrpottpatriot.7293:

Wcf web service (afaik) builds heavily on xml that’s also the reason why there’s a great support for that (LinqtoXml, etc.)

As the api uses json not xmlwe have to use a different method to de-serialize the json contetn into .Net objects we can use. The .Net framework gives us a tool for that, the DataContractSerializer. However DCS is slow, not as slow as the other alternative – JavaScript Serializer – but still slower than the Json.Net library we were using. (see here: for features of Json.Net and performance: https://json.codeplex.com/).

The reason why we are suing third party de-serializes is as poke said: “not to reinvent the weel”. Why write custom code, which we have to maintain if a better solution is out there.
It’s the same as if you would buy a car, without wheels because you make them in your own garage instead of buying goodyear stuff

steckums.9108:

Sounds great. I’ll do some things on the codeplex site today and tomorrow and publish the thing as soon as possible.

Ok, I’m done with the codeplex page (can be found here: https://gw2dotnet.codeplex.com/). The code is pretty basic and rudimentary as I didn’t have much time and I’m fairly new to the whole WebRequest thing. I’m willing to learn though and I hope to do so by providing to this project.

Just wanted to let you know, I’m using your API. I’ve found at least one error so far:

WVW→Models→Match is a struct, which is great and usable.
WvW→Models→MatchDetails is NOT a struct (it’s a class). Changing it to a struct, and re-adding the .dll to my project solved the problem of being able to access that datatype.

Ruhrpottpatriot.7293:

Yeah little bug there. Fixed it and it should be in the repository now.

On another note: We completely rewrote the events engine (or at least are 90% done with the rewriting) which we will implement to the other areas asap. The user now has a manager class which will manage the cache and everything else. This removed thee need for singletons. As the end-user now cannot directly create instances of the calling functions, but only the manger itself.
This ensures that the cached data is used, presumed that the user only creates one manager class!

Some examples should be up in the next few days.

steckums.9108:

Yeah little bug there. Fixed it and it should be in the repository now.

On another note: We completely rewrote the events engine (or at least are 90% done with the rewriting) which we will implement to the other areas asap. The user now has a manager class which will manage the cache and everything else. This removed thee need for singletons. As the end-user now cannot directly create instances of the calling functions, but only the manger itself.
This ensures that the cached data is used, presumed that the user only creates one manager class!

Some examples should be up in the next few days.

Since you’re using RestSharp for this, how would I use this for a Windows 8 application? The target versions of .NET aren’t compatible between the two.

Ruhrpottpatriot.7293:

it should be. WE are targeting .Net 4.0 and Win 8 should have 4.5. Compatibility is therefore given.

Ruhrpottpatriot.7293:

Some examples are up. Currently they are pretty bare-bones, but they’ll grow with time:
https://gw2dotnet.codeplex.com/documentation

steckums.9108:

It looks like in the latest version, GW2.NET/V1/WvW was not included in the source code, but if you open the project, it’s looking for a reference for WvWManager.cs (And, of course, the model and DataProvider folders are empty).

Ruhrpottpatriot.7293:

Yeah my bad. I worked in University on the WvW, then shelved the changes to continue work later at home, but forgot to submit the changes into the repository.

steckums.9108:

Next question: If I were to want to query the API on a specific event to see if the status has changed, how would I do that with your wrapper?

Ruhrpottpatriot.7293:

Updated documentation to have examples on how to retrieve events.

Rohan.1403:

Next question: If I were to want to query the API on a specific event to see if the status has changed, how would I do that with your wrapper?

If you’re going to be checking for changes consider using Gw#. It provides events for exactly what you need.

Ruhrpottpatriot.7293:

Currently our Wrapper does not support a event status change, this is the next big thing we want to implement.

DarkSpirit.7046:

Are you guys using RestSharp? I am not familiar with it but how well does it support deserializing the flags array from the item details into a bit flags enum?

Sorry for jumping the gun because you have not worked on that yet.

Ruhrpottpatriot.7293:

Yes we are using RestSharp to get the Json from the ANet server. However we are using Json.Net to deserialize the string as Json.Net is the fastest Json deserializer out there and we can use every bit off speed.

DarkSpirit.7046:

Yes we are using RestSharp to get the Json from the ANet server. However we are using Json.Net to deserialize the string as Json.Net is the fastest Json deserializer out there and we can use every bit off speed.

Cool, so am I. I had to implement my own JSONConverter to deserialize the flags JSON array to a flags enum. It works but I am not too happy with the way I did it so I am looking for a more elegant solution.

I’ll wait for you guys to get to the items API then.

Ruhrpottpatriot.7293:

OK I fixed a bug whereas the wrapper did not parse the wvw objects properly. THis is now fixed.

The documentation also has recieved a new topic on how to retrieve the wvw matches.

Healix.5819:

Cool, so am I. I had to implement my own JSONConverter to deserialize the flags JSON array to a flags enum. It works but I am not too happy with the way I did it so I am looking for a more elegant solution.

I’m assuming something like?

[Flags]
enum ItemFlags 
{ 
    None = 0, 
    AccountBound = 1 << 0, 
    HideSuffix = 1 << 1, 
    NoMysticForge = 1 << 2, 
    NoSalvage = 1 << 3, 
    NoSell = 1 << 4, 
    NotUpgradeable = 1 << 5, 
    NoUnderwater = 1 << 6, 
    SoulBindOnAcquire = 1 << 7, 
    SoulBindOnUse = 1 << 8,
    Unique = 1 << 9
};

And then however you read the original flags,

ItemFlags flags = ItemFlags.None;
foreach (string flag in item.flags)
    flags |= (ItemFlags)Enum.Parse(typeof(ItemFlags), flag, true); //try/catch this for unknown types

It’s a pretty simple way to get an enum representation of their string array.

DarkSpirit.7046:

Cool, so am I. I had to implement my own JSONConverter to deserialize the flags JSON array to a flags enum. It works but I am not too happy with the way I did it so I am looking for a more elegant solution.

I’m assuming something like?

[Flags]
enum ItemFlags 
{ 
    None = 0, 
    AccountBound = 1 &lt;&lt; 0, 
    HideSuffix = 1 &lt;&lt; 1, 
    NoMysticForge = 1 &lt;&lt; 2, 
    NoSalvage = 1 &lt;&lt; 3, 
    NoSell = 1 &lt;&lt; 4, 
    NotUpgradeable = 1 &lt;&lt; 5, 
    NoUnderwater = 1 &lt;&lt; 6, 
    SoulBindOnAcquire = 1 &lt;&lt; 7, 
    SoulBindOnUse = 1 &lt;&lt; 8,
    Unique = 1 &lt;&lt; 9
};

And then however you read the original flags,

ItemFlags flags = ItemFlags.None;
foreach (string flag in item.flags)
    flags |= (ItemFlags)Enum.Parse(typeof(ItemFlags), flag, true); //try/catch this for unknown types

It’s a pretty simple way to get an enum representation of their string array.

Something like that except that I have to make the ItemFlags type more generic since I would want to use the same JSONConverter for the other flag-like enums.

I also use the EnumMember attribute to map certain JSON strings to enum flags since I am picky with the way my flags are spelled, but that is just extra code to handle it.

Ruhrpottpatriot.7293:

Json.Net can directly deserialze to enums.

haven an enum like this:

/// <summary>
/// Enumerates all possible states an event can be.
/// </summary>
public enum GwEventState
{
/// <summary>
/// The event is running now.
/// </summary>
Active,

/// <summary>
/// The event has succeeded.
/// </summary>
Success,

/// <summary>
/// The event has failed.
/// </summary>
Fail,

/// <summary>
/// The event is inactive,
/// and will only become active once certain criteria are met.
/// </summary>
Warmup,

/// <summary>
/// The criteria for the event to start have been met,
/// but certain activities (such as an NPC dialogue) have not completed yet.
/// After the activities have been completed, the event will become Active.
/// </summary>
Preparation,

/// <summary>
/// The event is invalid.
/// For now no further information were released by Arena Net
/// </summary>
Invalid
}

and then have a property on the model like this:

/// <summary>
/// Gets the state.
/// </summary>
[JsonProperty(“state”)]
public GwEventState State
{
get { return this.state; }
}

DarkSpirit.7046:

Json.Net can directly deserialze to enums.
snip

I meant deserializing enum Flags from JSON array, look at Healix’s example. For straight deserializing into enum, you can just use the built-in StringEnumConverter.

In order to make ItemFlags a generic type and also use the bitwise OR operator on it, I had to use the dynamic type. That works but I am not happy with resorting to that and I wonder if there is a better way.

Ruhrpottpatriot.7293:

Yes that’s what my example also does. You create an object and annotate it with the [JsonProperty] attribute if the naming differs from the naming in the json string. Json.Net will then automatically try and find the enum and deserialize into.

You could also not define a type and let Json.Net deserialize for itself. But then you’dprobably get an object back.

Look how we did it in Gw2.Net (V1.World namespace and there look at the models).

DarkSpirit.7046:

Yes that’s what my example also does. You create an object and annotate it with the [JsonProperty] attribute if the naming differs from the naming in the json string. Json.Net will then automatically try and find the enum and deserialize into.

You could also not define a type and let Json.Net deserialize for itself. But then you’dprobably get an object back.

Look how we did it in Gw2.Net (V1.World namespace and there look at the models).

I know all that but what we wanted is to deserialize JSON like this:

“flags”:[“AccountBound”,“SoulBindOnUse”]

into:
[Flags]
public enum GW2APIFlagsEnum
{
None = 0,
AccountBound = 0×01,
SoulBindOnUse = 0×02,
HideSuffix = 0×04,
NoMysticForge = 0×08,
NoSell = 0×010,

}
So the property looks like:

public GW2APIFlagsEnum Flags;

So Flags can take on the state of BOTH AccountBound and SoulBindOnUse at the same time, according to the JSON array, since they are bit-flags. You can use them like this by checking if individual bits are set:

if ((item.Flags & GW2APIFlagsEnum.NoSell) != 0) ….

if ((item.Flags & GW2APIFlagsEnum.SoulBindOnUse) != 0) ….

Ruhrpottpatriot.7293:

Is an IEnumerable<GW2APIFlagsEnum> a solution?

DarkSpirit.7046:

Is an IEnumerable<GW2APIFlagsEnum> a solution?

I already have a solution but I am just looking for a better one, if it exists. I had to implement my own JSONConverter to deserialize the JSON array values into bits and bitwise-OR them (see Healix’s post above). But I had to use the dynamic type to make my JSONConverter generic enough for all the Flags enum, which I am not happy about.

Ruhrpottpatriot.7293:

I already have a solution but I am just looking for a better one, if it exists. I had to implement my own JSONConverter to deserialize the JSON array values into bits and bitwise-OR them (see Healix’s post above).

Well on that topic I’m not that great. I recommend you ask your question over at Stackoverflow I’m sure they can help you with it.

On a more topic related note:
The basic implementation of the items & recipe API part is now in the depot/repository (don’t be confuse if I say depot in one sentence and repository in another I work with SVN and P4 on other projects and they use different terms but they mean the same).

You now can query the server for all the available recipes (WARNING!!!:: This will take a very, very long time) or for one recipe at a time.

I’m still looking for willing people to help me and the others code, especially on the subject of async requests.

DarkSpirit.7046:

You now can query the server for all the available recipes (WARNING!!!:: This will take a very, very long time) or for one recipe at a time.

I’m still looking for willing people to help me and the others code, especially on the subject of async requests.

Thanks.

I would advise people to use the data dump for items and recipes because these are not suppose to change often except maybe after a game patch. You can read the data into a dictionary when your app starts up, which doesn’t take too long, then do a dictionary lookup after that. This saves bandwidth and improves the performance of your app significantly at the same time.

Granted that the api is still beta and there is an existing bug where some items are missing. Cliff is looking into that. But after release, I expect the data to be more stable.

It is so fast, that I use this data to build item tooltips on my app on the fly. I cached the images of course. It would not have been possible if I have to go fetch data from the web each time I want to build up a tooltip as the mouse pointer moves across the items.

You can use the item and recipe data dump here:

https://www.dropbox.com/sh/zucn218fhneva3c/-MjOkUsTtI

Discussion:

https://forum-en.guildwars2.com/forum/community/api/Data-dump-All-recipes-and-created-items/first#post2129446

Ruhrpottpatriot.7293:

Yeah I’ll probably do that. Still, I want to build querying functionality first (that should be ready by tomorrow or the day after), then build async support plus data refreshing around it and then think about a more efficient way of caching the data.

This project mainly aims to be a helper library (aka, you request an event and get the map and world details with it so you don’t have to query the api three times, the library will do that) not a fully fledged program, So I’m inclined to let caching of data more permanently than a session fall into the end-users hand (Still I might offer some “adapters” to ease the use of caching for the end user).

Ruhrpottpatriot.7293:

Hey fellas,
our implementation now includes the colour api. This has thrown the items implementation a bit back but I hope I can deliver it to you in the next days.

Ruhrpottpatriot.7293:

I’m somewhat proud to present you the first implementation of the items api in GW2.Net

I believe this is on of the most complete implementation (if not the most complete) of the items api in any wrapper currently out there.

The code is already in the depot, as it builds, but it hasn’t been tested yet so there are definetly some bugs in there. But the unt tests are running and I’m fixing those asap.

You can get all items or just a single item by it’s id. The other new thing is the caching. If you request one item by it’s id the wrapper will check if the items cache is already populated, if it is it will pull the item out of the cache. If the cache is not populated it will make a connection to the api and pull the single item from the server without touching the overall cache.

If you find any bugs please report them at the Issue Tracker

DarkSpirit.7046:

Hey Ruhrpottpatriot, I noticed that you deserialized item flags into a List. Although that is easier to deserialize, it is going to be harder for your client to use.

For example, if I am to look for items that are AccountBound, then I would have to search through the Flags List for AccountBound for each item. This is why I deserialize it to bit flags so I can just do this:

if ((pair.Value.Flags & GW2APIFlagsEnum.AccountBound) != 0) {…}

If you agree, let me know if you want to see my item flags JSONConverter or any part of my code if you want.

Ruhrpottpatriot.7293:

First: I’m deserializing into a collection not a list (IEnumerable<T> is specifically not a list, for good reasons)

Second: On first sight it may look like deserializing into a collection is more work, but if you use LINQ (which is the recommended way of accessing the collections in this wrapper), the code becomes much shorter. Example: I want to get all items that are account bound, I’d do it like this:

ItemsManager manager = new ItemsManager();

// need to convert to a list for the Find all method but everything is also doable with just IEnumerable<T>
var itemsCollection = manager.Items.ToList();

var accountBoundItems = itemsCollection.FindAll(i => i.Flags.Contains(ItemFlags.AccountBound));

It’s slightly longer than your code, but it’s much easier to implement for the developer on the wrapper side.

You can do so much with LINQ, and the performance cost of being evaluated each time the function is called can easily be circumvented and is usually (even here in collections with 8k to 10k items in a collection) negligible)

DarkSpirit.7046:

You are converting to a List first anyway and that is still an O(n) operation compared to mine which is an O(1) operation. Furthermore, to check for the flag, my client only needs 1 line of code so the complexity is much lower.

Ruhrpottpatriot.7293:

The fist line is to get the general collection, this is needed at your code too I presume.

Furthermore with LINQ you don’t have to convert it into a list. I just wrote the operation upon the existing unit test I had in place for geting al items.

I’m currently in the train to get home and the mobile internet is mediocre and I don’t have the VS (my MBA is running low on battery), but I can assure you that the whole operation is also possible with an IEnumerable. It should be SelectMany<TSource, TResult>(IEnumerable<TSource>, Func<TSource, IEnumerable<TResult>>) or something in that direction.

// Get all items
ItemManager manger = new Manger();

// use SelectMany() to get all items that are account bound
var items = manger.Items.SelectMany(accountBound =>accountBound.Flags.Contains(ItemFlags.AccountBound));

Yes in the end your operation is faster (duh! its O(1) after all :P), but I deem the speed benefit not great enough to justify the additional work I and the other developers have to do, unless you can prove that it is really that much faster.

DarkSpirit.7046:

Yes in the end your operation is faster (duh! its O(1) after all :P), but I deem the speed benefit not great enough to justify the additional work I and the other developers have to do, unless you can prove that it is really that much faster.

Well like you said, I do deem it to be more efficient because it is O(1) versus O(n). You are comparing the speed at which a computer processor performs a bitwise-AND versus FindAll. Even though I like LINQ myself, there is just no comparison the bitwise-AND operation is going to be faster. Sorry you would just have to trust my words since I don’t have the time to do performance testing.

Like I have said, if you prefer my approach, I am willing to share my code to reduce the amount of work you guys need to use it. My code uses the dynamic type, from .NET 4, so I hesitated to share it earlier.

Ruhrpottpatriot.7293:

I’m not denying that your method is faster, I’m aware of that. However things that speak against your code:

  • The expression if ((pair.Value.Flags & GW2APIFlagsEnum.AccountBound) != 0) {…} is not per se more friendly for the end user. My code on the other hand tells the user what it does. In the statement itemsReturn.Where(item => item.Flags.Contains(ItemFlags.AccountBound)) even a newcomer to c# can see what is happening. Even more so id use I’d query notation.
  • Your code has 60 characters (without anything in-between the curly brackets, which is still needed and without the call to the api/cache to get the items in the first place). My code is 95 characters in length (with conversion to the final collection, but without the call to the api/cache). Therefore I deem your code – without knowing a more detailed example – marginally shorter than mine.
  • It is more work to implement. Not harder to implement not necessarily harder, but it is more work. Therefore it is more error prone and more time consuming than a simple conversion to a collection.

On the other hand your code is definitely faster. I’m currently running a simple stopwatch experiment to get the rough time it needs to call the api, get all items and filter the items that are account bound. I’ll post the times as soon as I get them.

For me personally I don’t deem the performance gain via the use of bitwise-AND to be great enough to justify a lengthier implementation time (we might have the current api complete but who knows what will come in the future and how many enums we might need) with potentially more errors.

I also want to make the code as easy to use for the end user as it possibly can be. I also want to keep as many doors open as I can, therefore the simple conversion to a collection of enums, no more no less (side effect: I simply declare them and leave Json.Net to do the rest)

In the end I have to decline thankfully to your offer.

/edit: I find this post from a SO user on the performance cost of LINQ pretty good.

DarkSpirit.7046:

That seems to be a fair analysis and in the end, it is your call. Thanks for looking into it though.

Ruhrpottpatriot.7293:

So, I did the following query in LINQPad, with a slightly modified data dump from this forum (all I did was to add {"items":{ to the beginning, so I could parse it more easily and I attached the modified json to this post).



//read from file to leave the api call time out
string[] lineArray = File.ReadAllLines(@"C:\recipe_created_items.json");
string jsonString = string.Join("", lineArray);

/Deserialize
var items = JsonConvert.DeserializeObject&lt;Dictionary&lt;string, Dictionary&lt;int, Item&gt;&gt;&gt;(jsonString)["items"].Values;


Stopwatch watch = new Stopwatch();

List&lt;long&gt; ticksCounter = new List&lt;long&gt;();

for (int i = 0; i &lt; 1000; i++)
{
        watch.Start();

        var accountBound = items.Where(item =&gt; item.Flags.Contains(ItemFlags.AccountBound));
        watch.Stop();

        ticksCounter.Add(watch.ElapsedTicks);

        watch.Reset();
}

var averageTicks = ticksCounter.Average();

Debug.WriteLine("Average time 24 items out of 6849: {1} ms({0} ticks)", averageTicks, averageTicks / TimeSpan.TicksPerMillisecond);

// Result: Average time 24 items out of 6849: 0.0003 ms(3 ticks)

If I convert the query into a list I get the following result:
[qutote]
Average time 24 items out of 6849: 0.5012394 ms(5012.394 ticks)
[/quote]
I had to measure the ticks, milliseconds was too inaccurate, all I got was 0 :P

And I guess I can live with 3 ticks and even with ~5000ticks time. The real bottleneck is not LINQ but the server, if you do a whole query you will wait about 15 to 30 munutes :P
Btw: the first call takes about 4600 ticks every query after that goes between 0 and 2 ticks.

DarkSpirit.7046:

Lol…I knew the bottle-neck would be the server which was why I asked you to take the data dump in the first place.

https://forum-en.guildwars2.com/forum/community/api/NET-Implementation/first#post2131073

This would impact performance even more than what we talked about recently. Asking your user to wait 15 to 30 minutes is extremely long.

You should try a bitwise-AND operation and see how many ticks it takes, if it even registers. If you take the outer loop of going through nth items in your list + going through your Flags enum List, your algorithm becomes O(n-square) while mine would be O(n). If ArenaNet introduces more items and Flags in the future, which they probably would, your algorithm performance would be impacted more than mine, at least in theory. But I can understand if you think that bitwise operations are not as intuitive and you decided to sacrifice efficiency to make your code look more intuitive.

Ruhrpottpatriot.7293:

yeah well one millisecond are 10000 ticks so half a millisecond is still fast enough. Even if Anet introduces so much flags that it goes up another 5000 ticks, no one should complain about the speed. We are not in real life business applications where every ms counts or you loose half a million Dollar

In my eyes using bitwise flags for every bit of efficiency is a little bit over engineering the code.

But If you drop me your dll and a sample unit test code I’ll gladly run it through LINQ-Pad

DarkSpirit.7046:

yeah well one millisecond are 10000 ticks so half a millisecond is still fast enough. Even if Anet introduces so much flags that it goes up another 5000 ticks, no one should complain about the speed. We are not in real life business applications where every ms counts or you loose half a million Dollar

In my eyes using bitwise flags for every bit of efficiency is a little bit over engineering the code.

But If you drop me your dll and a sample unit test code I’ll gladly run it through LINQ-Pad

I am not sure if you are seeing this from the perspective of an actual app. Performance is critical when you are displaying large amounts of data where the code to access the item data don’t just get run once, but many times. Any performance inefficiency in your core library data accessors get multiplied.

That said, I don’t wish to sound all “doom-and-gloom” if you don’t use bitwise operations. Your library performance may just be good enough for most apps, plus you do have better code readability your way, I’ll give you that.

I am not ready to drop my dll yet as I am in the middle of making changes. But I can share my code to deserialize JSON flags to bit flags so you can copy-and-paste to integrate it to yours and test it, if you wish.

Ruhrpottpatriot.7293:

The thing is: Why should the code get run more than once? There is no need to run multiple subsequent queries to filter the data. And even then. My test did exactly that. 1000 iterations of the LINQ code. The first was at 5000 ticks the other 999 were at 0 to 2 ticks or ~0,0001 milliseconds, that is simply not measurable for the human.

Even if we are talking about 5000 ticks or 0,5 ms – the time of the first query – a normal human will not be able to make the difference between 0,5ms or 1ms. After all the average human reaction time is 1 second or 1000 ms.

It is the same with Google, you just feel it is faster because google tells you with a number it is faster the human brain will not be able to tell if it’s faster.

I will start thinking about changing the background code if we get to times about 150 to 200ms but we are far from that.

Just for teh lulz I ran the following code:



 Stopwatch watch = new Stopwatch();

            watch.Start();

            string[] lineArray = File.ReadAllLines(@"C:\recipe_created_items.json");

            string jsonString = string.Join(string.Empty, lineArray);

            var items = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<int, Item>>>(jsonString)["items"].Values;

            var biggerList = items.ToList();

            biggerList.AddRange(items);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);

            var totalItems = biggerList.Count;
            
            IEnumerable<Item> accountBound = null;

            for (int i = 0; i < 1000; i++)
            {
                accountBound = items.Where(item => item.Flags.Contains(ItemFlags.AccountBound));
            }

            watch.Stop();

            Debug.WriteLine("Average time {3} items out of {2}: {1} ms({0} ticks)", watch.ElapsedTicks, (watch.ElapsedTicks / TimeSpan.TicksPerMillisecond), totalItems, accountBound.Count());

and this code



string[] lineArray = File.ReadAllLines(@"C:\recipe_created_items.json");

            string jsonString = string.Join(string.Empty, lineArray);

            var items = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<int, Item>>>(jsonString)["items"].Values;

            var biggerList = items.ToList();

            biggerList.AddRange(items);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);
            biggerList.AddRange(biggerList);

            var totalItems = biggerList.Count;

            Stopwatch watch = new Stopwatch();

            List<long> ticksCounter = new List<long>();

            IEnumerable<Item> accountBound = null;

            for (int i = 0; i < 1000; i++)
            {
                watch.Start();

                accountBound = items.Where(item => item.Flags.Contains(ItemFlags.AccountBound));
                watch.Stop();

                ticksCounter.Add(watch.ElapsedTicks);
                watch.Reset();
            }

            var averageTicks = ticksCounter.Average();

            Debug.WriteLine("Average time {3} items out of {2}: {1} ms({0} ticks)", averageTicks, (averageTicks / TimeSpan.TicksPerMillisecond), totalItems, accountBound.Count());

The first one took 500ms to run, the second took 0.0897975 ms or 897.975 ticks. If I increase the for loop runs to 100000 it takes 0.003133942 ms or 31.33942 ticks to get all items that are flagged as account bound out of a list of 1753344.

DarkSpirit.7046:

The code needs to run more than once when you are looking for different items at different times. The performance does look good enough. I am curious though, if you need to check more than one flag (e.g. AccountBound + SoulBound, etc), how much does the performance differ, if at all.

Ruhrpottpatriot.7293:

The code needs to run more than once when you are looking for different items at different times.

That’s why every single lookup first looks if there is a cache and pulls the single item from the cache. Not before is a connection to the server made and the single item from the server pulled.

This is not implemented at every data provider, but I’m working to do that.

Also The next thing I want to include is asnyc support and then I want to change the data provider so that they can get the items from the disk or a database in addition to the server.

Also I have to correct myself the result for the iteration over the bigger list is
Average time 6144 items out of 1753344: 0.010616829 ms(106.16829 ticks) in the above code I was still iterating over the small list. Still the ms count is under 1 ms, so not noticeable.

As for your query: I ran this query:

accountBound = biggerList.Where(item => item.Flags.Contains(ItemFlags.AccountBound) && item.Flags.Contains(ItemFlags.NoSalvage));

and the result is: Average time 5376 items out of 1753344: 0.00635732 ms(63.5732 ticks)

and with the Unqique flag in addition: Average time 0 items out of 1753344: 0.006504914 ms(65.04914 ticks)

and

accountBound = biggerList.Where(item => item.Flags.Contains(ItemFlags.NoSell) && item.Flags.Contains(ItemFlags.SoulbindOnAcquire));

results in: Average time 2816 items out of 1753344: 0.010707205 ms(107.07205 ticks)

So from the results I make that more flags == faster. Which confirms my suspicion that the truly resouce intensive progress is the adding to the list. Which also explains that it takes 500ms to run the complete test, but only about 0.006 ms to run the LINQ query.

DarkSpirit.7046:

Thanks for the experiments. I dont think there should be any big performance issue with that so I am convinced.

On a side note, for enum flags, you can also use the Enum.HasFlag method to make your code more readable instead of checking the bit states yourself.

Ruhrpottpatriot.7293:

To use Enum.HasFlag() I’d have to decorate all enums with the Flags attribute and mark everything with bits. Enum.Has() flag is furthermore not in LINQ itself.

Since I did all the above tests with LINQ and my code as it is in the repository I cannot use the HasFlag() method.

/edit: I did some research on List<T> (since I did all the tests with List<Item>) seems the backing part of a list is in fact an array which holds – as per .Net specification the internal array has a size for up to 500 items. If the item count exceeds the list will double it’s capacity to allow storing more items.

I haven’t found out if the second resize is from 1000 to 2000 or simply from 1000 to 1500.

This would explain why the first of 1000 method calls in the first example takes 5000 ticks (create the list and add the first item) and all subsequent calls (simple adds) are that fast.

DarkSpirit.7046:

I don’t use flags on all my enums either. I only use enum flags in GameType, Item Flags, Restrictions, Infusion slot flags (i.e. Defense, Offense, Utility), and upgrade component flags because these come in the form of JSON arrays and can hold more than one enum value. But yes, I agree there would be quite a bit of work involved if you do the change.

You can pass a capacity parameter to the List constructor and test your theory.

Ruhrpottpatriot.7293:

Yeah I think I’ll test that out in the next few days when I’ve got a bit more time.

// edit: It further seems that if I use the syntactic sugar (i.e. from, in, select, where) with linq it performs slower than the method query (which makes somewhat sense, but I’d have to see the IL to confirm this).
Second: It also seems that if you specify the output type of a linq query instead of using var linq also performs slower.
See here and especially the comment from “Pavel” further down. (Keep in mind however that the first code is built upon a beta of LINQ and the code from pavel upon the final .Net 3.5 release. And I’m currently using 4.0 which is even faster)
Third: It also makes a huge difference to run the release code instead of just the VS code. All my tests I have made have used the debug release version. I’d have to make some tests with the release build

Ruhrpottpatriot.7293:

Ok a litte heads up for the people who don’t harcore spam F5 in the codeplex source tab or have it subscribed via RSS

Since the last update we have fixed many bugs, especially in the items wrapper. We have added a guild lookup functionality and we have updated the colours api to support the latest changes.

I hope we can keep up the current pace and start with the async support in a few days.

Ruhrpottpatriot.7293:

I’m proud to tell you taht we just released version 0.5.0.0 of our GW2.NET library. This marks our first official release besides the usual source code.
You can grab the pre compiled binaries together with the dependencies and the xml documentation files from our Codeplex Download page.

This is only a first step in the direction we want to go.
Our goal is to make this library as easy to use as a Bobby-Car! If you want to know where we are headed and want to follow us just drop by at our Codeplex page and subscribe.

Have fun working with this release.

Ruhrpottpatriot

DarkSpirit.7046:

Code looks pretty clean. Why don’t you return an interface to the client instead of a class?

I suggest looking into the Inversion of Control design pattern That should help make your *Data objects pluggable with test classes using test data or other data providers.

Ruhrpottpatriot.7293:

where should I return an interface? could you point me to the code in question?

DarkSpirit.7046:

where should I return an interface? could you point me to the code in question?

I am on vacation right now but, if I recall, by looking at your code in the past, didn’t you return ItemData to the client?

If you did, then you have created a dependency between the client code and your class.
Look into the design pattern to loosen the coupling between client code and your lib. For example, your Gw2ApiManager class seems like it can be modified into a Service Locator or you may decide to use a Dependency Injection pattern.

These are just some suggestions to loosen the coupling with your client code, so you may choose to ignore them if you like. I will not be offended.

timidobserver.7925:

So, is anyone able to help me figure out where I am going wrong at trying to get this to work. Here are my steps.

1.Downloaded the 0.5.0.0 release(this doesn’t happen if I use the latest source code. It works fine with the latest source code.)
2. Opened visual studio 2012 professional.
3. Started new project.
4. Right click references and added all of the dlls in the place that I saved the latest release.
5. Put using gw2dotnet.v1 in my new project.
6. Put the following items in my code directly from the example.
GW2DotNET.V1.World.WorldManager wm = new

GW2DotNET.V1.World.WorldManager();
var allEvents = wm.Events.ToList();

I got the following error.
Newtonsoft.Json.JsonSerializationException was unhandled
HResult=-2146233088
Message=Error converting value “Inactive” to type ‘GW2DotNET.V1.World.Models.GwEventState’. Path ‘events10.state’, line 11, position 99.
Source=Newtonsoft.Json

poke.3712:

1.Downloaded the 0.5.0.0 release(this doesn’t happen if I use the latest source code. It works fine with the latest source code.)

And that’s the problem The 0.5.0.0 release was released when the `Inactive` event status did not exist in the API yet. So whenever the API outputs an inactive event, the deserialization fails because there is no equivalent enum value it can map to.

Support for the status was apparently added in the version directly after the 0.5.0.0 release, so you should be fine using any newer version than the released one.

timidobserver.7925:

Makes sense. Thank you.

Ruhrpottpatriot.7293:

Long time no see!

After a few months on hiatus (Real Life, at least for me) we are back in action. We just released version 0.7.0.1 of the library and are working (hard) on the next bigger release.
You can grab the pre-compiled binaries HERE.
Of course you are also invited to grab the Source Code directly and modify it according to our license.

I also updated the first post with lots of new information, look around if you have the time!

As always we are looking for developers to help us out. If you think you have it in you, contact me here on the forum (with your Codepley username) or on Codeplex directly.

See you in the game.

Ruhrpottpatriot.7293:

Soooooo…..
Nothing new on the development front, well almost.
I took some time to get a NuGet package up and running. Now updating will be even easier. You can grab the NuGet package here

Ruhrpottpatriot.7293:

So heads up for the days after christmas:

I hope to get the events implementation done before new year, but cannot guarantee it. Before that I’ll update the package with better documentation that will be available online via NuDoq.

Have a happy christmas and new year

Ruhrpottpatriot.7293:

We just released version 0.8.01 of our api. With this release the current API implementation is done (save mumble and chat links).
You can grab the new version on the Codeplex Download page or via NuGet .

The new documentation is up in parts and the rest will follow shorty (I hope).

Have fun with the new version.

Ruhrpottpatriot.7293:

A small bug fix release: Grab it via Codeplex or NuGet

Changes:

  • Fixed a bug where the source code would not build in release mode thanks to a wrong csproj element.
  • Changed version number to 0.8.0.2
  • Ran R# code cleanup function to unify code looks.
  • Removed optimize code from debug config for easier debugging.
  • Added x86 and x64 as platform targets to solution.

Ruhrpottpatriot.7293:

So a little heads up on what we are doing right now:

We are in the finishing steps of our big rework wich will make the library much easier to use for you and for us to maintain. The latest version which you can grab via our Codeplex page includes every endpoint the API has (except mumble), on contrast to the previous version which didn’t include the image endpoint.

Currently we are working on a way to reliable store the contents of the api after you fetched them. We are completely aware, that querying the item API is not the way to go as the content of that endpoint is not going to change often.
However, going with our design philosophy we want to make the library as much extendible as possible. Each user has it’s own preferences on how to store the cache, some will want to store them as JSON files again, some will want to use a backend database and some will want to use another method. We want to satisfy all of them and because of that we are not ready to release the new version just yet.

With the new release we will provide one standard implementation, so the whole package is ready to go directly after you installed it, but if something does not suit you, you can easily change it through dependency injection.

One of our coders (Steven Liekens) has written an example page. He will upload it in the next few days, so you can see what you can do with our library. After the release of the new version we will provide more examples (definitely a WPF integration, WinForms is still up to debate, as that API is going to vanish sooner or later)

Now back from the future to some current problems:

  • I am aware that the current version is not working with the latest GW2 patch, since it introduced a new property for items and therefore deserializing the JSON response will break. We will release a hotfix for that problem today or tomorrow.
  • I am also aware that the current documentation on NuDoq is not working. I am in contact with the site and hope to change that in the next few days.
  • I am more than aware that the documentation on the Codeplex page is not complete (far from it). I am currently a bit stressed with my university homework and have not much time for writing it. I hope to get it done in the next days.

At the end I want to thank my team for putting so much effort into this. Without you we would not be here today.

StevenL.3761:

Thanks for taking the time to post all that. You saved me a lot of typing. :P

Here’s the demo website that was mentioned in the post above: http://guildwars2netdemo.apphb.com/

This website is also entirely open-source (currently without a license, but I’m leaning towards the MIT license). To anyone reading this: I am desperately in need of someone who knows how to tame HTML/CSS/JavaScript and has experience with (or is willing to learn about) ASP.NET MVC 4.

Your job will be to:

  • figure out how to use the GW2.NET library (with my personal guidance)
  • provide feedback about code that we’ve written
  • develop example applications that demonstrate how the library can be put to good use

If you are this person, send me a private message. I check these forums at least daily.

Ruhrpottpatriot.7293:

A bit late for an Easter present, but we had to tackle some stuff, so forgive us.

Here is version 0.9.0.0 of the GW2.NET library. It already implements the new skins endpoint and is otherwise a spring cleaned version, with many improvements.

We also provide you now with a second package which uses RestSharp to make the API calls, if you prefer that install the additional package too.

As always you can either grab the library as binarys on our download site or via NuGet (R# implementation). NuGet is totally recommended over that standard download way.

StevenL.3761:

v0.9.1.0

I’ve gone ahead and updated the library to include all of the latest bugfixes and features that didn’t make it into the previous release. Mostly regarding the item_details endpoint.

You can get the updated binaries from the project page. The updated Nuget package should follow soon(ish).

Ruhrpottpatriot.7293:

So it has been some busy weeks for me, as you could have guessed for the lack of updates I did. Gladly the team did not stop working and we put out three new releases!

Some of you might have gotten them already from out Codeplex site, but those who rely on NuGet were surely disappointed.

Rejoice! I have updated the packages and you can get them just by updating the package in your solution.

Have fun coding.

Ruhrpottpatriot.7293:

We released version 0.9.6.0 and the hotfix 0.9.6.1 for the main GW2.NET library, we also released 0.9.6.0 for the Rest# specific implementation, as always you can grab it via NuGet as alwys

StevenL.3761:

Hey guys

I published version 0.9.9.0 of GW2.NET on the Codeplex project page.
This release adds support for all /v2/commerce services.

https://gw2dotnet.codeplex.com/

Enjoy!

StevenL.3761:

Hello again

You can now download version 0.9.10.0 of the library. This release adds support for the /v2/items service, and fixes some issues with the implementation for the /v1/item_details.json service.

https://gw2dotnet.codeplex.com/releases/view/133598

Enjoy!

Aerodin.2795:

Awesome work, as always. Thanks guys!!

TehGear.8702:

Hey Steven,

I currently have an issue with this method: IDictionaryRange<TKey, TValue> FindAll(ICollection<TKey> identifiers); it gives back no prices at all. (GW2DotNET.V2.Commerce.PriceService)

Regards

StevenL.3761:

Can you give me the collection of identifiers that causes the problem? I’ll take a look at what’s going on.

TehGear.8702:

var prices = PriceService.FindAll(new Collection<int>() { 9591, 12852 }); //Doesn’t work

var p1 = PriceService.Find(9591); // Works
var p2 = PriceService.Find(12852); // Works

StevenL.3761:

I’m taking a look at it. Bug confirmed, but I’m not sure why this is happening. Both “Find()” and “FindAll()” use the exact same serialization engine. The only difference is that one object is part of a collection, the other isn’t.

Edit

Turns out it is a copy-paste-programming error. The ‘FindAll()’ method is talking to the /commerce/listings service instead of the /commerce/prices service. Thanks for the feedback!

TehGear.8702:

I was trying to find it myself, but I couldn’t find out how to reference the projects correctly.

StevenL.3761:

You only have to reference GW2.NET.dll and GW2.NET.Core.dll for that. Don’t reference the Contracts.dll libraries. You can reference other libraries, but you don’t have to.

TehGear.8702:

I mean I tried to find the bug, with debugging, but I couldn’t find out how to reference the projects properly.

StevenL.3761:

  • Open your solution
  • Select your main project in the solution explorer
  • Project | Add Existing Item… | GW2.NET.csproj
  • Project | Add Existing Item… | GW2.NET.Core.csproj
  • Project | Add Reference… | Solution | Projects | GW2.NET, GW2.NET.Core

edit

I see the problem now. The GW2.NET.Core.csproj configuration file wasn’t source controlled for some reason.

StevenL.3761:

I uploaded version 0.9.11.0 of the library. This is a bugfix release that, among others, fixes the problem with the ‘FindAll()’ method on the prices service.

https://gw2dotnet.codeplex.com/releases/view/133644

TehGear.8702:

I’m not sure if it’s FindAll or in general, but when I call the FindAll function with more than 350 Ids, it get’s a parser error instead of the endpoint is limited to 200 error.

I think, it’s because of the hardlimit of the URL.

StevenL.3761:

That’s just our error logic tripping over the HTML response when it was expecting JSON instead. Nothing much that I can do about besides ensuring that the content type header is application/json before attempting to parse the error content.

TehGear.8702:

No problem, just wondered.

Besides, great work so far, thank you ;-)

Ruhrpottpatriot.7293:

MERRY CHRISTMAS FOLKS (or whatever you might celebrate these days)

Finally after months of hard work we have released version 0.9.12 of our popular library. Much has been done since the last version. Finally everything the ANet API has to offer is present in our library. You can query your Quaggans as well as you can use the integrated GW2 Mumble support.

But what has changed exactly? Now that’s too much to remember, but here are the key points:

  • Every endpoint covered
  • Unified query system for everything, safe some few nodes where appropriate documentation is written as you read this text here. You don’t have to keep in mind that the maps endpoint is queried in a different way than events, or items. We did the work for you, so you can code more efficiently and with less errors.
  • Many optimizations to the codebase. Now almost everything can run in parallel. This means, you can query the whole items database in around 30 seconds, opposed to the previous 15 minutes.
  • More strongly typed object, meaning less magic strings and thus even less errors than before.

But where to go from here on?
Sadly we have to announce that this release will be the last release for .NET 4. Operating systems based on XP or even older are in steady decline. With the release of Windows 10 in a few months XP will be more than 13 years old and it’s time to retire it. This and the move to open source for the .NET framework means a wider audience for .NET 4.5 and above. Of course we want to get the biggest user base we can have and this is not possible with .NET 4 anymore.
Therefore we will move to at least .NET 4.5 with the coming versions. We waited so long because we didn’T forget the XP users out there and we wanted to give them the best experience we could offer.
But as I already said: Windows 10 and an open source .NET framework put the nails in the coffin for the current framework version.

I know not everyone is happy about this, but it is final.

So long folks. Happy coding over your (hopefully) free days.

P.S. Yes I know the first post and the Codeplex site are not updated yet. This will happen in the next few hours and days.

Aerodin.2795:

Nice job guys. I know a lot of work went into this release, and it shows. Thanks for continuing to update and be active with your library!

Ruhrpottpatriot.7293:

So I finally got to update the first post. Now with more information for everyone free of charge.

So that you know: We are currently implementing the last of the recently released endpoints. They should be finished in a week, not because they are so hard to implement, but it takes time and between university exams and a job most of the team is currently busy elsewhere.

StevenL.3761:

I think that the NuGet package is outdated. This sounds like a bug that I fixed months ago in 0.9.12.1

Does the same code crash for any other repository besides QuagganRepository?

StevenL.3761:

The Codeplex project page always has the most recent package. There are two ways to install the binaries.

1)
download the zip-file, extract the contents, and add references to GW2NET.dll and GW2NET.Core.dll to your project. Also add references to Json.NET (can use NuGet).

2)
download the nupkg file, move it to a directory somewhere memorable (e.g. C:\NuGet), add that folder as a NuGet package source in the NuGet package manager settings, then use the package manager to install the package from the local directory instead of the online NuGet feed

StevenL.3761:

FYI: we don’t filter unknown cultures like “th-TH”. Instead, we let the API decide which language to use for the response. For “lang=th”, the response defaults to English, so that’s what you get.

StevenL.3761:

I’ll check it out.

Oh… yeah, the code is still broken. Seems that I didn’t fully understand the problem last time I came across this bug.

Update: a new package is available on the Codeplex project page. This package includes a fix for the null references in the QuagganRepository class.

StevenL.3761:

It works now, thanks : )
In Quaggans part the IDictionaryRange<string, Quaggan>.TotalCount property doesn’t work for me, it always shows 0.

I’ll check it out.

*In ChatLinks part when you decode I think you are using wrong type, it should be ItemChatLink not ChatLink, as it doesn’t have the ItemId property.

Decoding as ‘ChatLink’ is by design. The reason is because we use the same ‘Decode()’ method for all types of chat links, not just item chat links.

You can use a safe cast in combination with a null check to get the item identifier.


    int GetItemId(string chatLinkAsBase64)
    {
        var chatLink = ChatLink.Factory.Decode(chatLinkAsBase64) as ItemChatLink;
        if (chatLink == null)
        {
            return -1;
        }

        return chatLink.ItemId;
    }

Alternatively, you can use the generic ‘Decode<T>()’ overload. Beware that this method throws exceptions (I forgot which type) if the input is not an item chat link .


    int GetItemId(string chatLinkAsBase64)
    {
        try
        {
            var chatLink = ChatLink.Factory.Decode&lt;ItemChatLink&gt;(chatLinkAsBase64);
            return chatLink.ItemId;
        }
        catch
        {
            return -1;
        }
    }

StevenL.3761:

In Quaggans part the IDictionaryRange<string, Quaggan>.TotalCount property doesn’t work for me, it always shows 0.

I remember now. This happens because the quaggans API returns the X-Result-Count header, but not the X-Result-Total header. I’ll create a new issue on GitHub.

Edit
https://github.com/arenanet/api-cdi/issues/15

darthmaim.6017:

This won’t compile, as chatLink.ItemId will be marked red due to declaration ChatLink chatLink and ChatLink class has no ItemId property.

It probably should be this:

ItemChatLink chatLink = ChatLink.Factory.Decode("[&AgHblwAA]") as ItemChatLink;

// Write to console, but of course you can use it wherever you want.
Console.WriteLine(chatLink.ItemId);

StevenL.3761:

Ohhh… yeah, that’s an error in the documentation. Nice find!

Ruhrpottpatriot.7293:

I updated the Nuget feed to be the same version as the Codeplex page. Should work now too.

@Steven: If you update to a new version, send me a mail. There is a greater chance I’ll see that

Ruhrpottpatriot.7293:

So everyone. I haven’t posted here in a while, since I was busy with my university classes.
You can expect a new release this weekend. The release will NOT contain any of the new authenticated endpoints.

To clarify:
With the next release we are officially moving out of Beta and into version 1.0. This version will be the last to support the v1 endpoints. Future versions will throw a warning and at some point an error (expect this to be around 1.5 or so).
Of course this does not hold true for endpoints which are not yet available through the v2 interface.

Since 1.0 is a good foundation to implement bigger changes in the deployment process and the like, you will also see a change in Version numbers. From 1.0 onwards we are using semantic versioning so you can finetune which versions you want to use and which not.

As for the authenticated endpoints, expect them around 1.1 or 1.2, that will be released in a month or so (I hope).

Ruhrpottpatriot.7293:

It took us about a week, but we finally released version 1.0.0 of our popular library. We are sorry for the delay, but we had to fix some last minute issues so everything now and in the future is going smoothly.


  • Split the package into smaller packages to make updating and publishing more modular and therefore faster. See bottom of this post more more details!
  • Made GetParameters and GetPathSegment in DiscoveryRequest virtual so they can be used with the /v2/floors url style
  • Changed constructor of abstract class FactoryBase to protected
  • Stylecop fixes across the board
  • Added Support for v2/floors endpoint and made it publicly available although the api endpoint is currently disabled.
  • Added Support for v2/maps endpoint
  • Added Support for v2/skins endpoint
  • Added Support for v2/continents endpoint
  • Added Support for v2/files endpoint
  • Renamed WvW property in Factoryfor V1 to WorldVersusWorld
  • Added missing ObjectInvariant methods.
  • V2 Factories now implement RepositoryFactoryBase to reduce code repitition
  • Added obsolete warnings for all currently available v2 endpoints
  • Added an obsolete error for the v1 events endpoint since it is already disabled
  • Fixed some bugs in the request classes
  • Added interface and model class for v2/files since the old model/interface is not compatible with the new api layout
  • Updated StyleCop settings

Still there are some things to consider when upgrading:
First of all: We changed the ID of the NuGet package to be in line with the namespaces we use in the project itself. However updating from 0.×.x to 1.0.1 is still possible with a helper package. To use this helper package you don’t have to do anything besides updating your GW2.NET NuGet Package. The helper package is appropriately labeled and will download all required packages by itself. After the update process has been completed you can remove the helper package without consequences.

You then might notice that you have dozens of GW2.NET.xyz packages in your package manager. As already stated in the changelog we have split our one big package into multiple smaller ones so we can deliver updates more frequently in the future. This also allows users to modularise the packages according to their needs.
For erxample: A website which only displays WvW scores will definitely not need the items package. So the developers can simply download GW2.NET World versus World Matches and be done with it.
This of course requires more work form the user since he by himself has to create and maintain the repositoriesby himself, which is currently done by the GW2.NET main package, but this is not hard and documentation on this topic will be updated in the next weeks.

This said: For the masses of developers installing the GW2.NET main package is absolutely sufficient!

For anything else, just leave a message here or read the documentation over at Codeplex

And now: Happy coding

~~ Ruhrpottpatriot

P.S. We will be moving to another OSS provider in the near future. We will keep you appraised of that, should anything change for you.

Lone Wolf.4129:

Did anyone got this working with unity?