Rally Rest Api - DynamicJsonObject how to check if key exists - rally

I am trying to display a list of stories (hierarchical requirements) and defects from Rally on a web page.
We have a custom field called "InfraID" on our defects, but not on our hierarchical requirements. Is there a way of detecting whether each DynamicJsonObject has a key called "InfraId" to avoid it throwing an exception?
I've tried TryGetValue, Contains, HasKey thinking it was being treated as a dictionary but I keep getting a KeyNotFoundException. "The given key was not present in the dictionary"
This is being used in a Razor ASP.NET MVC view.
#if (story.HasKey("InfraID"))
{
<td>#story["InfraID"];
</td>
}
So I can't figure out what that if statement can be to avoid an exception being thrown. Story is of type Rally.RestAPI.DynamicJsonObject.
I'm trying to use the same html whether its a defect or a story, as everything else has worked ok. It's just because it's a custom attribute on a defect.
In case it helps the stack trace that seems relevant is:
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Rally.RestApi.DynamicJsonObject.GetMember(String name)
at Rally.RestApi.DynamicJsonObject.TryGetMember(GetMemberBinder binder, Object& result)
So I'm hoping that doesn't mean I can't check for its existence in my front end code.

Try HasMember:
bool hasInfraId = story.HasMember("InfraID");
You can find the methods/namespace for Rally.RestApi.DynamicJsonObject in the full api docs out on the developer portal here:
Rally REST API .NET Namespace

Related

What is ActionId in the log entry when using serilog in ASP.NET Core application?

So looking at the logs created by serilog I see ActionId value that is some type of GUID. I know this is added by ASP.NET Core app by default but what exactly is this value?
One example of log entry contains following entries (among others):
ActionId: 1fbc88fa-42db-424f-b32b-c2d0994463f1
ActionName: /Index
I notice that ActionId can be different for the same ActionName but what exactly it represents? And for what good use can ActionId be used when I am searching through my logs?
It's just simply unique ActionDescriptor that asp.net core generate for your app.
I'm not so sure why are you curious at this... but this prove what's i'm saying.
I notice that ActionId can be different for the same ActionName
ActionId will survive the whole application life-time, but when you re-deploy the app, the ActionDescriptor got initialized. Therefore, difference Id.
And for what good use can ActionId be used when I am searching through my logs
Clearly a better way to search your log, like when using elastic, fields.ActionId: "YourActionIdHere" will give you all the request that touch the Action method.
Of course, the moment you saw difference ActionId, means your app got re-deployed. But actually... I've never using that, since we got plan what and when the app will release.

Deserializing Media field fails in Piranha CMS

Modifying Piranha for 'headless' scenario: I separated the api into its own REST API, and the MVC into its own UI that calls the REST API. Mostly it works well, but now an obstacle. My REST API serializes the result from the Piranha api, and my MVC web deserializes it into a Piranha StandardPage type. This works for all fields except Media, which is always null. Using newtonsoft.Json.
The Media property is defined in Piranha.Extend.Fields.MediaFieldBase with internal set, which explains why I can't deserialize into it. So I added a [JsonProperty] attribute to the Media property. Once I did this, then the Media field was correctly deserialized by the MVC, and images appeared.
But then I found this broke something else: in the manager, when I try to save a page with a Hero image, the Save buttons spins, stops as though it succeeded, but the toast never appears saying success. I set Debug logging for Microsoft.AspNetCore.Mvc.Infrastructure, and see there's a model state error when this happens:
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed controller factory for controller Piranha.JA.Manager.Controllers.PageApiController (Piranha.JA.Manager)
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter[1]
The request has model state errors, returning an error response.
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Request was short circuited at action filter 'Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter'.
I can debug into the PageApiController for most operations, but when Save executes none of the breakpoints are hit.
I also tried just removing the internal accessor from set (and removing [JsonProperty]) and got the same behavior: can deserialize Media ok but trying to save page with a Hero from manager gives model state error.
Would love to write up some documentation on how to go headless if we can solve this.
We've been debugging this one for a few days, can anyone help?
In the branch I pushed I actually changed the accessor to public, so you shouldn’t need the additional attribute. This is also merged to master and will be released in 8.3.
Regards
I posted this on the Piranha CMS github and one of its authors, Hakan Edling, answered in just a few hours:
"The root issue is that when a new item is selected in the manager in the media picker, the media model that is assigned contains a formatted string size "xxx kb". When ASP.NET tries to deserialize this into a long it fails.
So changing the following line in the .vue components for the media-based fields:
this.model.media = media;
to
this.model.media = {
id: media.id,
folderId: media.folderId,
type: media.type,
filename: media.filename,
contentType: media.contentType,
publicUrl: media.publicUrl,
};
Resolves the serialization error in the manager when the Media property is public.. I'll push this fix to a new branch so you can test it."
And soon after,
"Please test with the branch https://github.com/PiranhaCMS/piranha.core/tree/features/make-mediafield-media-public"
I still must add the [JsonProperty] attribute to the Media field in MediaFieldBase class, so my deserializer can access the internal set method. Hakan's fix makes it so this attribute doesn't break the manager.
Thank you for your quick response Hakan, you rock!

Change Key of HttpContext.Request.Query item in ASP.NET Core

I am trying to work around a issue with a 3rd party filter. My current plan is to put a filter in front of that filter to "fix" the query string so it does not error out.
I made an ActionFilterAttribute and added it into the filter list. It is running fine. I am adding my logic in the OnActionExecuting method.
The first item of context.HttpContext.Request.Query has a Key that is a json structure. I need to change that Key to be {}.
Problem is that both context.HttpContext.Request.Query and context.HttpContext.Request.QueryString are read-only.
How can I alter the context.HttpContext.Request.Query or the context.HttpContext.Request.QueryString?
EDIT - The Underlying Problem:
BreezeJS did a minimal level upgrade to support .NET Core. In this upgrade, part of the code expects that every call that has any parameters to return an IQueryable (QueryFns.cs Line 32). From reading the code it seems like this is an error (the calling function (the actual filter) seems to just expect null to be returned not an Exception.)
Either way, this makes moving to .NET Core very hard.
I considered my other options and if this fails, I will continue to pursue them:
Submit a pull request to fix the issue: The project has not accepted any pull requests in over a year and a half. So it seems unlikely my request will be taken.
Fork my own branch: I would rather not have to create and maintain a separate version with my own build and publishing pipeline.
Find a way to make the Breeze filter ignore the call when the result is not an IQueryable: I am currently looking into this one. (This question.)
Find a way to send my call from the client differently so that breeze ignores calls that do not return IQueryable: The return type of the call is owned by the service. And this is an issue with the service. I would rather not have to have tight coupling between the service and the client such that the client is crafting workarounds for service filter issues.

Exceptions and StatusCode in ASP.NET Core MVC

We have UseExceptionHandler (handle Exeptions) and UseStatusCodePages (handle StatusCode). Why in ASP.NET Core MVC we using StatusCodeResult than just handy extend Exception?
UseExceptionHandler is generally used to catch up unexpected errors and preset them in a more friendly manner to the user.
Whereas status codes are more important in REST API to signal the client the success or failure (and specific cause of the failure) of the specific operation.
Controller action should never throw exception and access a specific resource (i.e. db record) which doesn't exist you should return 404 (not found). When passed data is invalid rest apis return "400 bad request", on success 200. When new resource is created 201 (with "Location" header which contains the url to the new resource, see CreatedAtAction method of the controller class).
With views it works differently where you render the error directly into the HTML Code. You can also return status codes with MVC-esque view controllers and handle it with UseStatusCodePages (i.e. showing a generic NotFound.cshtml template for resources which don't exist).
Also your question sounds like you want to use exceptions to set status code, this is wrong for a couple of reasons.
Exceptions should be (as their name suggest) exceptional; Read: when something unexpected happens. For example if you try to withdraw a negative balance from your bank account and further processing it makes no sense or becomes impossible.
When you expect an error, you should return a result or handle it differently. For validations you should use Result classes (i.e. IdentityResult from ASP.NET Core Identity, which contains a Success property and a property which contains a list of error messages in case the operation or the validation fails).
Throwing and catching Exceptions is quite expensive, so they should really only be thrown when (as pointed above) something unexpected happens. Not finding a record is nothing unexpected.
(Ab)using exceptions for flow control (deciding which code path to execute) is just wrong. That's what if/switch and patterns like strategy pattern are for. Exceptions will just make the code unreadable and harder to maintain.

How to define API keys in restFul meteor?

I am new to rest api in meteorjs. I am trying to run the example explained in The meteor chef but getting this error:
ReferenceError: APIKeys is not defined
at Object.API.authentication (api/config/api.js:4:19)
at Object.API.connection (api/config/api.js:16:34)
at Object.API.handleRequest (api/config/api.js:28:26)
at [object Object].Router.route.where (api/pizza.js:9:9)
at boundNext (packages/iron_middleware-stack/lib/middleware_stack.js:251:1)
at runWithEnvironment (packages/meteor/dynamics_nodejs.js:110:1)
at packages/meteor/dynamics_nodejs.js:123:1
at [object Object].urlencodedParser (/Users/mac/.meteor/packages/iron_router/.1.0.12.13720an++os+web.browser+web.cordova/npm/node_modules/body-parser/lib/types/urlencoded.js:84:40)
at packages/iron_router/lib/router.js:277:1
at [object Object]._.extend.withValue (packages/meteor/dynamics_nodejs.js:56:1)
The code is same as explained in the example
It is because you didn't created APIKeys mongo collection as shown here: https://github.com/themeteorchef/writing-an-api/blob/master/code/collections/api-keys.js
Add this file to your project and then it'll work.
Here is explanation from post you linked:
Next, we try to insert a new key for our user into the APIKeys collection. Wait a minute! Where did this come from?! This collection was setup beforehand, but let’s talk about why we have a separate collection to begin with. The reason we want to separate our API key storage from the more predictable location of our user’s profile (the writable portion of a user’s record in the Meteor.users() collection) is that by default, the profile object is writable.
So you just missed this part of tutorial where they created APIKeys collection.