In the Azure WebJobs SDK, we have the IBinding interface. This interface has a method BindAsync with two params, but I can't understand what is the first param object value and when this overload method will be called.
The same question related ITriggerBinding interface.
I have tried to find the answer in the SDK code source. I know that BindingSource contains a dictionary of parameters where the key is an argument name and value is an argument value that will be provided to the BindAsync method, but I cannot understand what these arguments are and where they come from?
UPDATE
IBinding.BindAsync Method Returns Task<IValueProvider>.
The usage of IBinding.BindAsync.
Microsoft.Azure.WebJobs.Host.Bindings.IBinding.BindAsync(Microsoft.Azure.WebJobs.Host.Bindings.BindingContext)
Sample Code
public async Task BindAsync_String()
{
ParameterInfo parameterInfo = GetType().GetMethod("TestStringFunction").GetParameters()[0];
HttpTriggerAttributeBindingProvider.HttpTriggerBinding binding = new HttpTriggerAttributeBindingProvider.HttpTriggerBinding(new HttpTriggerAttribute(), parameterInfo, false);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/myfunc?code=abc123");
request.Content = new StringContent("This is a test");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/text");
FunctionBindingContext functionContext = new FunctionBindingContext(Guid.NewGuid(), CancellationToken.None, new TestTraceWriter(TraceLevel.Verbose));
ValueBindingContext context = new ValueBindingContext(functionContext, CancellationToken.None);
ITriggerData triggerData = await binding.BindAsync(request, context);
Assert.Equal(0, triggerData.BindingData.Count);
string result = (string)triggerData.ValueProvider.GetValue();
Assert.Equal("This is a test", result);
}
From sample code(HttpTrigger), you will find request, context. They are two params in BindAsync. You will know the usage of BindAsync.
Related
I'm trying to add a sharepoint list item with a content type using the graphclient.
I using this code:
ClientCredentialProvider authProvider = new ClientCredentialProvider(confidentialClientApplication);
GraphServiceClient graphClient = new GraphServiceClient(authProvider);
ContentTypeInfo ct = new ContentTypeInfo()
{
ODataType = "microsoft.graph.contentTypeInfo",
Id = config["AuditItemContentTypeId"]
};
var listItem = new Microsoft.Graph.ListItem
{
ContentType = ct,
Fields = new FieldValueSet
{
AdditionalData = new Dictionary<string, object>()
{
{"Title", "xxx"},
{"CreationTime", auditItem.CreationTime},
{"AuditItemId", auditItem.Id},// ID is used in sp
}
}
,
};
var addedItem = await graphClient.Sites[stc.CaptureToSiteId].Lists[stc.CaptureToListId].Items
.Request()
.AddAsync(listItem);
The addadsync fails with the message
2021-05-27T21:37:04.897 [Error] Executed 'ProcessAuditItem' (Failed, Id=d846ddc1-bb9d-4082-88b6-b6b3fa26afc8, Duration=507ms)Object reference not set to an instance of an object.
Anyone have an ide what i've done wrong? Any docs on doing this with the graph client in c# (not sending raw JSON... im trying to use the classes porovided). Is ther a way to turn on some verbose logging in the graphclient?
Russell
It is difficult to tell what is wrong with your code based on the information you have provided. Assuming you have checked that stc is not null: What kind of SharePoint field is AuditItemId? Also the exact ContentTypeId could be relevant. As far as I know, there is no additional logging that you can turn on. However, in the latest versions of the Graph SDK you can customize the GraphServiceClient to implement your own logging. First, create a class based on System.Net.Http.DelegatingHandler:
public class ExtensiveLoggingDelegatingHandler : DelegatingHandler
{
private readonly IExtensiveLoggingService _extensiveLoggingService;
public ExtensiveLoggingDelegatingHandler(
IExtensiveLoggingService extensiveLoggingService)
: base()
{
_extensiveLoggingService = extensiveLoggingService;
}
public ExtensiveLoggingDelegatingHandler(
HttpMessageHandler innerHandler,
IExtensiveLoggingService extensiveLoggingService)
: base(innerHandler)
{
_extensiveLoggingService = extensiveLoggingService;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
//add custom logging logic here
await _extensiveLoggingService.DocumentMSGraphApiCall(request, response);
return response;
}
}
I am using Dependency Injection to inject custom logging into the DelegatingHandler. The logger just writes all info (request url, request header, request body, response header, ...) into a log file, if a certain log level is configured. The handler needs to be injected into the GraphServiceClient in order to be called upon request execution:
var handlers = GraphClientFactory.CreateDefaultHandlers(
someMicrosoftGraphIAuthenticationProvider);
handlers.Add(new ExtensiveLoggingDelegatingHandler( _extensiveLoggingService));
var httpClient = GraphClientFactory.Create(handlers);
var graphServiceClient = new GraphServiceClient(httpClient);
I am having troubles trying to get information back from a Lambda Function in AWS. The Lambda function is behind API Gateway.
If I run the function straight from the Lambda console or from the API, works ok. If I call it with this code returns [].
I am not getting any problems if the token is correct and I can see inside the Lambda function the parameter 'LastUpdate'.
Here is the code:
public async Task<string> GetUpdates(long ticksLastCheck, string token)
{
string Error = "";
string response = "";
object data = new
{
LastUpdate = ticksLastCheck
};
var myContent = JsonConvert.SerializeObject(data);
var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
//I have tested without ConfigureAwait and did not work either
var responseSync = await _client.PostAsync("getUpdates", byteContent).ConfigureAwait(false);
if (responseSync != null)
{
//I have tested with await and did not work either. With await ".Result" should be removed from the line below.
var response2 = responseSync.Content.ReadAsStringAsync();
response = response2.Result;
}
return response;
}
If I call it from Postman works as well. Is there any header or parameter that Postman sends and I am missing?
My bad. The field in DynamoDB is a string and I was sending it as a long and never converting to string.
So as soon as I change:
object data = new
{
LastUpdate = ticksLastCheck
};
into this
object data = new
{
LastUpdate = ticksLastCheck.ToString()
};
I am getting the expected response.
Thank you.
I have been running into a very strange issue, and I am not even sure if this is an issue with my app or the web service I am calling.
I have a Web API Service with a Post method that accepts a complex parameter (it is my own custom object). In my Xamarin project I have some pretty straightforward code to call this service:
public async Task SubmitEReport(decimal amount, DateTime receivedDate,
byte[] image)
{
try
{
HttpClient client = new HttpClient();
var uri = new Uri("https://services.example.com/EPub/api/Expense/");
var eReport = new eReport()
{
UserName = "EMPLOYEE\" + Application.Current.Properties["username"].ToString(),
Cost = amount,
ReceivedDate= receivedDate,
ReceiptImageExtension = "jpg",
SubmittalDate = DateTime.Now,
Image = image
};
var json = JsonConvert.SerializeObject(eReport );
var content = new System.Net.Http.StringContent(json, Encoding.UTF8, "application/json");
content.Headers.Add("authorize-token", Application.Current.Properties["auth-token"] as string);
HttpResponseMessage response = null;
response = await client.PostAsync(uri, content);
var eResult = new EResult()
{
Success = response.IsSuccessStatusCode,
ErrorMessage = response.ReasonPhrase
};
return eResult ;
}
catch (Exception ex)
{
var errorResult = new eResult () { Success = false, ErrorMessage = ex.Message };
return errorResult;
}
}
The issue that I am having is that, when I test this on an Android the code works as expected: the service is called, the object passed over is not null and has the data in it. In short, the parameter binding works as expected. The same is not so on iOS: when I call the service using the app on an iPhone, I can see that it is reaching the service and the Post method, but the parameter binding is not working correctly as the object I am passing over is always null.
The issue is resolved. The problem was actually the size of the request. I discovered this in my Web Api service after examining the contents of the request object, and received an exception that the request length was exceeded. My solution was to increase the value of the property maxrequestlength in the web.config. This still does not explain why the request is so much larger in iOS than Android. Will follow up on this.
try to debug your code without using any async methods. async methods should work in general without any problems, but it's sometimes hard to comprehend how implemented logic actually behaves.
In general I want to export data from asp.net mvc application to Google Sheets for example list of people. I've already set up connection and authenticated app with my Google account (trough OAuth2) but now I'm trying to send my list of objects to api and then handle it in script (by putting all data in new file) and couldn't get my head around this.
Here is some sample code in my app that sends the request.
public async Task<ActionResult> SendTestData()
{
var result = new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).
AuthorizeAsync(CancellationToken.None).Result;
if (result.Credential != null)
{
string scriptId = "MY_SCRIPT_ID";
var service = new ScriptService(new BaseClientService.Initializer
{
HttpClientInitializer = result.Credential,
ApplicationName = "Test"
});
IList<object> parameters = new List<object>();
var people= new List<Person>(); // next i'm selecting data from db.Person to this variable
parameters.Add(people);
ExecutionRequest req = new ExecutionRequest();
req.Function = "testFunction";
req.Parameters = parameters;
ScriptsResource.RunRequest runReq = service.Scripts.Run(req, scriptId);
try
{
Operation op = runReq.Execute();
if (op.Error != null)
{
// The API executed, but the script returned an error.
// Extract the first (and only) set of error details
// as a IDictionary. The values of this dictionary are
// the script's 'errorMessage' and 'errorType', and an
// array of stack trace elements. Casting the array as
// a JSON JArray allows the trace elements to be accessed
// directly.
IDictionary<string, object> error = op.Error.Details[0];
if (error["scriptStackTraceElements"] != null)
{
// There may not be a stacktrace if the script didn't
// start executing.
Newtonsoft.Json.Linq.JArray st =
(Newtonsoft.Json.Linq.JArray)error["scriptStackTraceElements"];
}
}
else
{
// The result provided by the API needs to be cast into
// the correct type, based upon what types the Apps
// Script function returns. Here, the function returns
// an Apps Script Object with String keys and values.
// It is most convenient to cast the return value as a JSON
// JObject (folderSet).
Newtonsoft.Json.Linq.JObject folderSet =
(Newtonsoft.Json.Linq.JObject)op.Response["result"];
}
}
catch (Google.GoogleApiException e)
{
// The API encountered a problem before the script
// started executing.
AddAlert(Severity.error, e.Message);
}
return RedirectToAction("Index", "Controller");
}
else
{
return new RedirectResult(result.RedirectUri);
}
}
The next is how to handle this data in scripts - are they serialized to JSON there?
The execution API calls are essentially REST calls so the payload should be serialized as per that. Stringified JSON is typically fine. Your GAS function should then parse that payload to consume the encoded lists
var data = JSON.parse(payload);
I know many times this question has been posted over here. But i am not able to find solution for my problem.
I have create one web service and i have set method return type as JSON but method still returns XML.
Here is my method :
[WebMethod(Description = "LoginMethod")]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string doLogin(string UserName, string Password)
{
LoginSuccess objSuccess = new LoginSuccess();
UserInfo objInfo = new UserInfo();
objSuccess.success = "true";
objInfo.Token = "token";
objInfo.type = "usertype";
objInfo.username = "username";
objInfo.userid = "userid";
objSuccess.response = objInfo;
clsJSON objJSON = new clsJSON();
loginResponse = objJSON.ToJSON(objSuccess);
return loginResponse;
}
Here is my response :
<string>{"success":"true","response":{"Token":"token","username":"username","userid":"userid","type":"usertype"}}</string>
But i want this as :
{"success":"true","response":{"Token":"token","username":"username","userid":"userid","type":"usertype"}}
I am calling this method from that page which web service giving us to test method. Request method is HttpPost.
Please suggest me for this.
The problem is that you've either not specified or used the wrong accept request header. It should be application/json. Without the relevant javascript code used to fetch data in your question it's not possible to say what exactly you should put where though.