How can you hide a graghQL field in DGS framework. E.g. as below, what can you use so that title cannot be fetched or isn't visible to the client?
type Show {
title: String
actors: [Actor]
}
I don't think that is possible. However, you can set authentication roles by field, which means that only clients with specific roles are going to be able to fetch data from it.
I am attaching a sample from DGS documentation of how you can do it.
#DgsComponent
public class SecurityExampleFetchers {
#DgsData(parentType = "Query", field = "hello")
public String hello() {
return "Hello to everyone";
}
#Secured("admin")
#DgsData(parentType = "Query", field = "secureGroup")
public String secureGroup() {
return "Hello to admins only";
}
}
Related
I used the "no code" way to generate a Bot in Azure and connect it to a QnA Maker knowledge base.
I have then modified the code so that the Bot uses AdaptiveCards instead of HeroCards to support Markdown formatting in MS Teams channel (format used by QnA Maker).
I am trying to add SubmitActions to these adaptive cards when there are some prompts coming from the Knowledge Base. The objective is that if the user clicks on these SubmitActions it automatically send a message back to the Bot.
Please find below the code I implemented:
// adaptive card creation
var plCardBis = new AdaptiveCard(new AdaptiveSchemaVersion(1, 0));
plCardBis.Body.Add(new AdaptiveTextBlock()
{
Text = result.Answer,
Wrap = true
});
// Add all prompt
foreach (var prompt in result.Context.Prompts)
{
plCardBis.Actions.Add(new AdaptiveCards.AdaptiveSubmitAction()
{
Title = prompt.DisplayText,
Data = prompt.DisplayText
});
}
//create the the attachment
var attachmentBis = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = plCardBis
};
//add the attachment
chatActivity.Attachments.Add(attachmentBis);
return chatActivity;
This works fine in the WebChat however in Teams if I click on a prompt it generates an error. Looking on internet I found that I should use an object for the Data field for Teams, instead of a simple string:
"data": {
"msteams": {
"type": "imBack",
"value": "Text to reply in chat"
},
}
Do you know how I could do that in C#? How could I update my code to add this object for the Data field? The number of Actions can vary according to the question asked by the user...
Any help would be greatly appreciated
Basically, there are two options for what you can attach to "Data" - either a plain string value, or any custom object. For your scenario, you need a custom object, so you need to define a class in your project to match what you need, something like:
public class MsTeamsDataResponseWrapper
{
[JsonProperty("msteams")]
public MsTeamsResponse MsTeamsResponse { get; set; }
}
public class MsTeamsResponse
{
[JsonProperty("type")]
public string Type { get; set; } = "imBack";
[JsonProperty("value")]
public string Value { get; set; }
}
then you'd use it like this:
...
Data = new MsTeamsDataResponseWrapper() { MsTeamsResponse = new MsTeamsResponse() { Value = prompt.DisplayText } }
...
In this case "Type" already defaults to "imBack", but you could also use it for "messageBack" at a later stage if you want to overwrite the default.
ASP.NET Core MVC has a great model binding & model validation subsystem which supports almost any scenario. But when developing APIs things can go a little more complicated.
Suppose we have a model class with a property XYZ which is annotated with [MinLength(5)].
public class ViewModel
{
[MinLength(5)]
public string XYZ { get; set; }
}
If anything goes wrong with this property what MVC will give you is something like this:
{ "XYZ": [ "The field XYZ must be a string or array type with minimum length of '5'" ] }
But this is not what the client needs! The client needs an object with specific details. She will create her own message however she wants to:
{ "error": "minLength", "property": "XYZ", "minimum": 5 }
Possible Solutions:
You can use InvalidModelStateResponseFactory to generate customized responses. It gives you the ActionContext which contains the ModelState property. But all you can do is to process error messages which are pure strings! That could lead to some problems.
Another option is to completely disable the MVC Validation and implement one for yourself.
I appreciate any other solutions.
For general validation message, it is pure string. And for minLength and minimum are different for different validation attribute. I am wondering how the client will check the different node.
For server side, InvalidModelStateResponseFactory would be better to return json object. and you need to check the ValidationAttribute for return different object like
services.Configure<ApiBehaviorOptions>(o =>
{
o.InvalidModelStateResponseFactory = actionContext =>
{
var error = new Dictionary<string, string>();
foreach (var key in actionContext.ModelState.Keys)
{
foreach (var parameter in actionContext.ActionDescriptor.Parameters)
{
var prop = parameter.ParameterType.GetProperty(key);
if (prop != null)
{
var attr = prop.GetCustomAttributes(typeof(ValidationAttribute), false).FirstOrDefault() as ValidationAttribute;
if (attr is MinLengthAttribute minLengthAttribute)
{
error.Add("Error", "minLength");
error.Add("Property", key);
error.Add("minimum", minLengthAttribute.Length.ToString());
}
}
}
}
return new BadRequestObjectResult(error);
};
});
I'm trying to call my API using postman, but the problem I'm facing is my API is using PUT method which takes enum object as a body..
How can I send enum in postman.. please help.
export enum TestStatus {
allCandidates,
completedTest,
expiredTest,
blockedTest
}
this is my enum , I'm using Angular 2.
With a method taking the enum as the body, the enum value needs to be entered without curly brackets, simply
"expiredTest"
or
2
directly in the Body tab (with raw and JSON(application/json) and an ASP.NET Core backend).
Providing you have a method that takes [FromBody]TestStatus status as a parameter.
Click on Body tab and select raw, then JSON(application/json).
Use this Json:
{
"TestStatus": "expiredTest"
}
Send!
I think above is your case as you stated: "take enum object as a body". Below are some more trivial ingredients:
If you have a parameter like [FromBody]MyClass class and its definition as
public class MyClass
{
public Guid Id { get; set; }
public TestStatus ClassStatus { get; set; }
}
Then you modify your Json as:
{
"Id": "28fa119e-fd61-461e-a727-08d504b9ee0b",
"ClassStatus": "expiredTest"
}
Just pass 0,1,2... interger in the json body to pass enum objects.
Choose 0 if required to pass the first enum object.
Exmple:
{
"employee": 0
}
I have some custom fields on my User object that I want to access with APEX code in my VisualForce trigger. When I access it from a Formula field I get to use a nifty $User reference like this:
$User.my_prop__c
From APEX I have to query the User object by UserId like this:
[select my_prop__c from User where id = :UserInfo.getUserId()].my_prop__c;
Is there something baked into APEX already that would let me get at the user properties without the SOQL query? If not, does anyone know of a utility class for lazy loading and caching user properties so the overhead is minimal.
I would use something similar to the following code sample. It uses a singleton pattern to statically store the information in memory for the duration of your transaction. It's similar to the lazy loading that twamley proposed but I feel this is a much simpler approach.
Usage 1: UserUtil.CurrentUser.Email;
Usage 2: User someUser = UserUtil.getUser(someUserId);
This will allow you to access the same information on the current user or other users in the system. Notice the queryUsers method just returns a query result. This makes it easy to add and remove fields from your query as it is isolated in its own method keeping things simple.
Note: that this code pulls in all users when used. Most orgs do not have multiple hundreds of users so heap size shouldn't be a concern. But if it is you can just modify the queryUsers() method to only return active users or filter down based on other criteria.
public class UserUtil {
//Protected Members
private static final UserUtil instance = new UserUtil();
private Map<Id, User> mapUsers;
//Properties
public static User CurrentUser {
get { return getUser(UserInfo.getUserId()); }
}
//Constructor
private UserUtil() {
mapUsers = new Map<Id, User>(queryUsers());
}
//Public Methods
public static User getUser(Id userId) {
if (instance.mapUsers.containsKey(userId)) {
return instance.mapUsers.get(userId);
}
else {
throw new InvalidUserIdException('Unable to locate user id: ' + userId);
}
}
//Private Methods
private List<User> queryUsers() {
return [SELECT
Id
, Name
, UserName
, Email
, Alias
FROM
User];
}
//Internal Classes
public class InvalidUserIdException extends Exception {}
}
I wrote my own utility class. I'm still interested in better techniques though.
This utility class lazy loads when the first property is accessed. Update_Closed_Won_Opportunities__c and Set_Opportunities_to_Closed_Won__c are my custom fields on the User object (visible only to System Administrators so people can't upgrade their permissions).
public with sharing class MyUserInfo {
private Id userId;
private User myUser; // Hold onto the user object once we've loaded it
// Default constructor uses the active user id
public MyUserInfo() {
userId = UserInfo.getUserId();
}
// Secondary constructor accepts a user id as a parameter
public MyUserInfo(Id someOtherUserId) {
userId = someOtherUserId;
}
// Only called one time when we first need it so grab all of the custom fields now
private void LazyLoadUser() {
System.AssertNotEquals(null, userId);
myUser = [
SELECT Update_Closed_Won_Opportunities__c, Set_Opportunities_To_Closed_Won__c
FROM User
WHERE id = :userId
];
System.AssertNotEquals(null, myUser, 'Unable to load user with id ' + userId); // could return defaults instead
}
// Getters (be sure to include each field in the SOQL of LazyLoadUser)
public boolean UpdateClosedWonOpportunities { get {
if (myUser == null) LazyLoadUser();
return myUser.Update_Closed_Won_Opportunities__c;
} }
public boolean SetOpportunitiesToClosedWon { get {
if (myUser == null) LazyLoadUser();
return myUser.Set_Opportunities_To_Closed_Won__c;
} }
}
Here is my trigger utilizing that class. The first line myUserInfo = new MyUserInfo(); doesn't run any SOQL. That won't happen until the first custom get property is used. Subsequent calls don't need SOQL.
trigger LockClosedOpportunity on Opportunity (before update) {
MyUserInfo myUserInfo = new MyUserInfo();
for (Opportunity o : trigger.old)
{
if (!myUserInfo.UpdateClosedWonOpportunities && o.StageName == 'Closed Won')
trigger.newMap.get(o.Id).addError('You do not have permission to change an Opportunity after it has been set to Closed Won.');
}
for (Opportunity o : trigger.new)
{
if ( !myUserInfo.SetOpportunitiesToClosedWon && o.StageName == 'Closed Won' && trigger.oldMap.get(o.Id).StageName != 'Closed Won' )
o.addError('You do not have permission to set an Opportunity to Closed Won.');
}
}
It reads similar to $User in formulas and I don't have to worry about tacking on multiple SOQL calls when one (or zero) suffices.
I want to display data in Listbox without using any DLL.And my webservice responding in json format.
My Web service Response is as below.it has more than 800 records
[
{
"st_id":"1",
"st_name":"name xyz"
},
{
"st_id":"2",
"st_name":"name ABC"
},
{
"st_id":"3",
"st_name":"name HIJK"
},
{
"st_id":"4",
"st_name":"name OPQ"
},
]
my Class for the data is as below
[DataContract]
public class Student
{
[DataMember=("st_id")]
public bool st_id { get; set; }
[DataMember=("st_name")]
public string st_name { get; set; }
}
i m trying serialize object using DataContractJsonSerializer & m getting WS response in Stream.But i am not able to serialize.Suggest links or basic tutorial for Serilize and Deserilize of the json
DataContractJsonSerializer stdserialize =
new DataContractJsonSerializer(typeof(Student));
Student stuser = (Student)stdserialize.ReadObject(responseStream);
so please help for the json response parsing & suggest link for datacontract and all which gives knowledge from basics.
Thanks,
You declared st_id as a bool, but the type of data you're trying to deserialize is string (which can be converted to numbers - not to booleans). Try declaring it as string and it should work.
Also, the response is an array of objects, so the type you should use is Student[]:
DataContractJsonSerializer stdserialize =
new DataContractJsonSerializer(typeof(Student[]));
Student stuser = (Student[])stdserialize.ReadObject(responseStream);