Skip to main content

Forums / Support / Halo API Support

HaloSharp (A C# Wrapper) (v2.0.1.0 - 2017-03-22)

OP Furiousn00b

  1. 1
  2. ...
  3. 2
  4. 3
  5. ...
  6. 4
I ran into the above 'NonSeasonal' unhandled exception, as well, but I haven't had time to dig into or work around it. I'm working on pulling stats for all the members in my company, and I'd like to do this in 4 requests of 25, instead of 100 individual requests (so the rate limit doesn't kill how long it takes).

Furiousn00b, Any updates on handling this exception?

Btw, love the wrapper - thanks for building it! <3
I ran into the above 'NonSeasonal' unhandled exception, as well, but I haven't had time to dig into or work around it. I'm working on pulling stats for all the members in my company, and I'd like to do this in 4 requests of 25, instead of 100 individual requests (so the rate limit doesn't kill how long it takes).

Furiousn00b, Any updates on handling this exception?

Btw, love the wrapper - thanks for building it! <3
I'll work on something in a few minutes and push out a fix ;)
Took some extra time tonight to get this fix in and extend the caching functionality somewhat.

v1.3.0.0 (GitHub | NuGet) Release Notes:
  1. Fixed an issue with unhandled HighestCsrSeasonId values (Reported by 'b01000100' and 'RHIT Propensity').
  2. Added the ability to specify cache durations (expiration). Metadata, Profile, and Stats can be independently set (or not at all).
  3. Fixed a couple of spelling mistakes. Breaking change :)
v1.3.1.0 (GitHub | NuGet) Release Notes:
  1. Fixed an issue where all results were being cached indefinitely when CacheDuration is not set.
Recommend updating to v1.3.1.0 over v1.3.0.0 as soon as possible (Unless you have unlimited memory to work with :O)
Hey Furiousn00b, I was wondering if you could look at something for me. I am seeing an issue with the GetMedals() query. Here are the scenarios:

Quote:
1. Compile everything with Newtonsoft.Json version 8.0.3 (latest)
  • This runs and debugs fine in Visual Studio 2015
  • Running it outside of Visual Studio (i.e. just copying all necessary files to a different location) causes the program to hang and logs an error in Windows. The error is a System.IO.FileLoadException, and it says it is looking for Newtonsoft.Json 8.0.0.0
Keep in mind that the Newtonsoft.Json 8.0.3 DLL is in the appropriate place, right alongside the executable
Quote:
2. Compile everything with Newtonsoft.Json version 8.0.1 (there is no 8.0.0 through NuGet, so I figured I would get as close as I could)
  • This runs and debugs fine in Visual Studio 2015
  • Running it outside of Visual Studio (i.e. just copying all necessary files to a different location) causes the program to hang and logs an error in Windows. The error is a System.IO.FileLoadException, and it says it is looking for Newtonsoft.Json 8.0.0.0
Again, the file is in the correct location
Quote:
3. Compile everything with Newtonsoft.Json version 7.0.1
  • This will run in Visual Studio 2015, but it will error out inside of VS with a System.IO.FileLoadException at GetMedals(). It is again looking for Newtonsoft.Json 8.0.0.
  • Running it outside of Visual Studio works on everything but GetMedals(). The program no longer hangs when running, and it seems to perform all other functions from HaloSharp without issue.
I rarely ever use GetMedals(), so this is just now popping up for me.

I have tried this in my main application and a simple test application that just had a call to the GetMedals() query. I saw the same behavior. I am sure I could be missing something, so I figured I would ask to get your thoughts. If everything worked with 7.0.1, I would just stay there for now. However, I can't debug with that. If everything worked with 8.0.3, I would use it, but I can't deploy the application using that. For now, I have been working and debugging with 8.0.3 and then downgrading Newtonsoft.Json before final building. It isn't a big deal for me, but I was wondering what you thought about it.

I don't do dev work in VS professionally, so I apologize if this is just the norm.
b01000100 wrote:
Hey Furiousn00b, I was wondering if you could look at something for me. I am seeing an issue with the GetMedals() query.
What version of HaloSharp are you running? There were a number of new Medal Enums added in versions 1.2.2.0 and 1.2.3.0 (you'll need to use at least those versions, but I recommend the latest).

You should be able to use any version of Newtonsoft.Json, do you have a stack trace I can look at?

Edit: I haven't been able to reproduce this. I attempted the following:
  1. Create a new Console Application.
  2. Add HaloSharp (v1.3.1)
  3. Add Newtonsoft.Json package (v8.0.3)
  4. Write some sweet code that uses the GetMedals query.
  5. Run in Debug Mode (Visual Studio). (Project runs as expected)
  6. Run in Release Mode (Visual Studio). (Project runs as expected)
  7. Copied \bin\Debug to Desktop. (.exe runs as expected)
  8. Copied \bin\Release to Desktop. (.exe runs as expected)
\bin\Debug\Newtonsoft.Json.dll is version 8.0.3.19514 according to File Properties.
Hmm, it sounds like it is on my end. I will take another look when I get home. I am running the latest version of HaloSharp, as far as I know. NuGet doesn't indicate that there is a newer version available, from what I recall.

I appreciate you taking a look. I will let you know what I find out.
v1.3.2.0 (GitHub | NuGet) Release Notes:

  1. Updated BaseMatch model.
    • New property: GameVariantResourceId
    • New property: MapVariantResourceId
  2. Updated BasePlayerStat model.
    • New property: PlayerScore (Firefight Hype!?)
  • GameVariantResourceId and MapVariantResourceId appear to be similar to the MapVariant and GameVariant properties on the 'Stats : Matches for Player' endpoint.
Quote:
  • MapVariant: The variant of the map for this match. There are two sources of map variants: official map variants available via the Metadata API and user-generated map variants which are not available via the APIs currently. If the map variant for this match was an official map variant, then the structure will be as documented here. This will be null for campaign games.
  • GameVariant: The variant of the game for this match. There are two sources of game variants: official game variants available via the Metadata API and user-generated game variants which are not available via the APIs currently. If the game variant for this match was an official game variant, then the structure will be as documented here. This will be null for campaign games.

  • PlayerScore appears to always be null, I suspect it's being setup for Warzone Firefight except that it appears on all Match type endpoints; Arena, Custom, Warzone and Campaign. So who knows?
Hey Furiousn00b,

First of all, thank you for creating and maintaining HaloSharp! I've been using it recently and it's great.

I guess you've seen that a match events endpoint has just been added:

https://www.halowaypoint.com/en-us/community/blog-posts/halo-api-hackathon
https://developer.haloapi.com/docs/services/560af163e2f7f710cc79e517/operations/5702bc86e2f7f71ff4b2f927

Do you have any idea when you might get this added to HaloSharp?

Thanks again.
Seph wrote:
Hey Furiousn00b,

First of all, thank you for creating and maintaining HaloSharp! I've been using it recently and it's great.

I guess you've seen that a match events endpoint has just been added:

https://www.halowaypoint.com/en-us/community/blog-posts/halo-api-hackathon
https://developer.haloapi.com/docs/services/560af163e2f7f710cc79e517/operations/5702bc86e2f7f71ff4b2f927

Do you have any idea when you might get this added to HaloSharp?

Thanks again.
I've just woke up and the read the news.

It'll be out ASAP. Working on it now.
v1.4.0.0 (GitHub | NuGet) Release Notes:

Stats Endpoints:
  • Added new 'Events for Match' endpoint.
Edit: Took a bit longer than I thought, got distracted by french toast.
v1.4.1.0 (GitHub | NuGet) Release Notes:

Bug fixes:
  • Missed a opportunity to turn an int into a proper Enum (DeathDisposition)
Man, you work fast! Thanks for the support, Furiousn00b. I'm just getting into this for the competition, but am planning on using HaloSharp. Just wanted to say thanks in advance =)
Man, you work fast! Thanks for the support, Furiousn00b. I'm just getting into this for the competition, but am planning on using HaloSharp. Just wanted to say thanks in advance =)
No worries :) If you have any trouble or are running into any issues, give me a shout.

I hope that it helps you and best of luck!
v1.4.2.0 (GitHub | NuGet) Release Notes:

Updated MatchEvents model (read about it here).
  • Rename: KillerAttachmentIds to KillerWeaponAttachmentIds
  • Rename: KillerStockId to KillerWeaponStockId
Fixed a bunch of tests related to MatchEvents.
Hey FN - I'm "Hello World-ing," with the sample usage you have on Github, and I'm having some issues.
Namely, your Readme suggests this: (italics comment mine...)
Quote:
var developerAccessProduct = new Product
{
SubscriptionKey = "00000000000000000000000000000000",
RateLimit = new RateLimit
{
RequestCount = 10,
TimspSpan = new TimeSpan(0, 0, 0, 10),
Timeout = Timeout.InfiniteTimeSpan //set no timeout limit?
}
};
However, I can't get that code to compile. Changing these two lines however...
Quote:
var developerAccessProduct = new Product
{
SubscriptionKey = "00000000000000000000000000000000",
RateLimit = new RateLimit
{
RequestCount = 10,
TimeSpan = new TimeSpan(0, 0, 0, 10),
Timeout = TimeSpan.Zero//Am I still setting no timeout limit here? Same result if I say: Timeout = 0; ?

}
};
Since the changed code compiles and seems to work just fine, my initial thought is that the Readme just didn't get updated after some change... however, I've got this nagging feeling that I'm missing something very obvious, especially since that second edit is using TimeSpawn from above to return an interval of time... Clearly I'm off the path here.
Hey FN - I'm "Hello World-ing," with the sample usage you have on Github, and I'm having some issues.
Namely, your Readme suggests this: (italics comment mine...)
Quote:
var developerAccessProduct = new Product
{
SubscriptionKey = "00000000000000000000000000000000",
RateLimit = new RateLimit
{
RequestCount = 10,
TimspSpan = new TimeSpan(0, 0, 0, 10),
Timeout = Timeout.InfiniteTimeSpan //set no timeout limit?
}
};
However, I can't get that code to compile. Changing these two lines however...
Quote:
var developerAccessProduct = new Product
{
SubscriptionKey = "00000000000000000000000000000000",
RateLimit = new RateLimit
{
RequestCount = 10,
TimeSpan = new TimeSpan(0, 0, 0, 10),
Timeout = TimeSpan.Zero//Am I still setting no timeout limit here? Same result if I say: Timeout = 0; ?

}
};
Since the changed code compiles and seems to work just fine, my initial thought is that the Readme just didn't get updated after some change... however, I've got this nagging feeling that I'm missing something very obvious, especially since that second edit is using TimeSpawn from above to return an interval of time... Clearly I'm off the path here.
I've been meaning to write some better documentation for how it all falls together, but I usually get caught out making something instead :)

The Rate limit object has three properties
  • RequestCount the number of requests your 'API Product' allows every N seconds.
  • TimeSpan: This is the time bound that your 'API Product' allows.
The developer account allows 10 requests (RequestCount = 10) every 10 seconds (TimeSpan = 10).

The Timeout is how long you want to wait for HaloSharp's rate limiter to timeout (this will only occur when you're maxing out your rate limit).

For example (RequestCount: 10, TimeSpan: 10 seconds, Timeout: 2 seconds):

Your rate limit is 10 requests every 10 seconds and you burst your maximum 10 requests in a 1 second window. You don't want to wait 9 seconds (the remainder of your rate limit) for your next request to return, so you set a timeout of 2 seconds. After the HaloSharp's rate limiter waits for the 2 second timeout, it will return a HaloApiException exception.

Usually, I don't really care how long the next request has to wait, so I'll set the timeout to Timeout.InfiniteTimeSpan. At the absolute most, the longest a request should have to wait is equal to the amount of time set for TimeSpan. Setting Timeout equal to TimeSpan is probably more appropriate if you're not concerned with waiting.

Setting the Timeout to TimeSpan.Zero wlll probably result in some weird behavior. You're telling HaloSharp's rate limiter to wait TimeSpan.Zero before throwing a timeout exception :O
Hope that makes sense :)

Also, that spelling mistake is hilarious. I'll get it fixed soon.
Hey, thanks for working on this. It is a big help. I do have one request though. Would it be possible to mark all the models as partial classes? That way they can easily be extended and would make things a little easier. For example, I add an id to the matches so they can be cached in a database. Right now I inherit from the class to add the id, but it means I have to copy all the data over (using automapper). If it was a partial class, I could just add the id to the class and set it. There are other things I want to extend as well and it would be a big help.

On another note, how are others caching the data with .Net? I found that LiteDb works pretty well (it is a noSql database) but just found that it doesn't store timespans. So any duration values are lost. This would be easy to overcome with partial classes though.

Thanks again for your work.
Hey, thanks for working on this. It is a big help. I do have one request though. Would it be possible to mark all the models as partial classes? That way they can easily be extended and would make things a little easier. For example, I add an id to the matches so they can be cached in a database. Right now I inherit from the class to add the id, but it means I have to copy all the data over (using automapper). If it was a partial class, I could just add the id to the class and set it. There are other things I want to extend as well and it would be a big help.
I looked into this today. You can't have partial classes across two different assemblies. Half the class would be in HaloSharp, the other half would be in your assembly (this wont work).

I only have one idea at the moment (but it's not perfect). We'll use GetArenaMatchDetails as an example.

You would normally do this:
  • Call the following.
Quote:
...
HaloSharp.Model.Stats.CarnageReport.ArenaMatch arenaMatch = await session.Query(query);
...
You can do this:
  • Create a new class that inherits from HaloSharp.Model.Stats.CarnageReport.ArenaMatch as has your extended properties.
Quote:
public class ExtendedArenaMatch : ArenaMatch { public Guid MatchId { get; set; } }
  • Call the following:
Quote:
ExtendedArenaMatch extendedArenaMatch = await session.Get(query.GetConstructedUri());
This is a lower level call that session.Query usually does. The trade off for this is that you won't get to use the built in cache or query validation.

If you've got any other ideas (or a working example), I'm happy to discuss.
Hey, thanks for working on this. It is a big help. I do have one request though. Would it be possible to mark all the models as partial classes? That way they can easily be extended and would make things a little easier. For example, I add an id to the matches so they can be cached in a database. Right now I inherit from the class to add the id, but it means I have to copy all the data over (using automapper). If it was a partial class, I could just add the id to the class and set it. There are other things I want to extend as well and it would be a big help.
I looked into this today. You can't have partial classes across two different assemblies. Half the class would be in HaloSharp, the other half would be in your assembly (this wont work).

I only have one idea at the moment (but it's not perfect). We'll use GetArenaMatchDetails as an example.

You would normally do this:
  • Call the following.
Quote:
...
HaloSharp.Model.Stats.CarnageReport.ArenaMatch arenaMatch = await session.Query(query);
...
You can do this:
  • Create a new class that inherits from HaloSharp.Model.Stats.CarnageReport.ArenaMatch as has your extended properties.
Quote:
public class ExtendedArenaMatch : ArenaMatch { public Guid MatchId { get; set; } }
  • Call the following:
Quote:
ExtendedArenaMatch extendedArenaMatch = await session.Get(query.GetConstructedUri());
This is a lower level call that session.Query usually does. The trade off for this is that you won't get to use the built in cache or query validation.

If you've got any other ideas (or a working example), I'm happy to discuss.
I forgot about that. Thanks for looking into it. I'll look into the session.Get method or just keep doing what I'm doing.
  1. 1
  2. ...
  3. 2
  4. 3
  5. ...
  6. 4