ASP.NET Boilerplate background jobs abandoned - aspnetboilerplate

I am using asp.net boilerplate and running a background job that posts data to an external API.
The post is happening correctly but the background job is still been abandoned instead of deleting it from the backgroundjobs table.
Is there a way to force a successful job execution and only abandon it if it fails.
Code Below
using Abp.Reflection.Extensions;
using EErx.Middleware.RestAPIClient.Dto;
using Erx.Middleware.Configuration;
using Erx.Middleware.Models;
using Erx.Middleware.RestAPIClient.Dto;
using Erx.Middleware.TCPCommunicator.Models;
using Microsoft.Extensions.Configuration;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
namespace Erx.Middleware.TCPCommunicator.Jobs
{
public class PDStatusUpdateJob : BackgroundJob<PDUpdateJobArgs>, ITransientDependency
{
private readonly Log _log;
private readonly IConfigurationRoot _appConfiguration;
private readonly IRepository<DispenseMessageHeader, long> _dispenseMessageHeaderRepository;
private readonly IRepository<DispenseMessageScript, long> _dispenseMessageScriptRepository;
private readonly IObjectMapper _objectMapper;
public PDStatusUpdateJob(
Log log,
IRepository<DispenseMessageHeader, long> dispenseMessageHeaderRepository,
IRepository<DispenseMessageScript, long> dispenseMessageScriptRepository,
IObjectMapper objectMapper
)
{
_log = log;
_dispenseMessageHeaderRepository = dispenseMessageHeaderRepository;
_dispenseMessageScriptRepository = dispenseMessageScriptRepository;
_objectMapper = objectMapper;
_appConfiguration = AppConfigurations.Get(
typeof(TcpCommunicatorModule).GetAssembly().GetDirectoryPathOrNull()
);
}
[UnitOfWork]
public override void Execute(PDUpdateJobArgs args)
{
try
{
var output = new PDDispenseMessageDto();
var scriptOutput = new List<PDDispenseMessageScriptDto>();
var headerRecord = _dispenseMessageHeaderRepository.FirstOrDefault(x => x.MessageGuid == args.MessageGuid);
var dispenseMessage = _objectMapper.Map(headerRecord, output);
var scripts = _dispenseMessageScriptRepository.GetAllIncluding(p => p.Items).Where(x => x.DispenseMessageHeaderId == headerRecord.Id).ToList();
dispenseMessage.Scripts = _objectMapper.Map(scripts, scriptOutput);
var request = new RestRequest(Method.POST);
var requestMsg = dispenseMessage.ToJsonString(true);
var client = new RestClient(_appConfiguration.GetValue<string>("PDUpdateAPI"))
{
Timeout = -1,
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
};
request.AddHeader("Authorization", "Basic " + GenerateToken());
request.AddHeader("EntityDescription", "ERX");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json; charset=utf-8", requestMsg, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
if (response.ErrorMessage != null)
{
_log.Logger.Error(response.ErrorMessage);
}
}
catch (Exception e)
{
_log.Logger.Error(e.Message);
}
}
public static string GenerateToken()
{
var encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes("somestring"));
return encoded;
}
}
}

Related

How to retrieve the serialized field name of an Elasticsearch Nest.Field

I want to get the field name of a field which is created with Infer.Field<MyDocument>(doc => doc.StringField1).
Example code:
using System;
using Nest;
using Xunit;
namespace Elasticsearch.Tests
{
public class MyDocument
{
public string StringField1 { get; set; }
}
public class SerializeField
{
[Fact]
public void TestFieldName()
{
var connectionSettings = new ConnectionSettings(new Uri("http://myesdomain.com:9200"));
var client = new ElasticClient(connectionSettings);
var stringField = Infer.Field<MyDocument>(doc => doc.StringField1);
// TODO: Code to get then name of stringField when serialized
}
}
}
Can I leaverage the client in order to serialize the name of the stringField as it would do in any request?
Fortunately I found the answer myself:
Short:
client.SourceSerializer.Serialize(stringField, ms);
Complete:
using System;
using System.IO;
using System.Text;
using Nest;
using Xunit;
namespace Elasticsearch.Tests
{
public class MyDocument
{
public string StringField1 { get; set; }
}
public class SerializeField
{
[Fact]
public void TestFieldName()
{
var connectionSettings = new ConnectionSettings(new Uri("http://myesdomain.com:9200"));
var client = new ElasticClient(connectionSettings);
var stringField = Infer.Field<MyDocument>(doc => doc.StringField1);
string fieldName;
using (var ms = new MemoryStream())
{
client.SourceSerializer.Serialize(stringField, ms);
ms.Position = 0;
using (var reader = new StreamReader(ms, Encoding.UTF8))
{
fieldName = reader.ReadToEnd();
}
}
Assert.Equal("\"stringField1\"", fieldName);
}
}
}
There is a better solution that uses a Nest.FieldResolver.
using System;
using Nest;
using Xunit;
namespace Elasticsearch.Tests
{
public class MyDocument
{
public string StringField1 { get; set; }
}
public class TestClass
{
[Fact]
public void TestFieldName()
{
var connectionSettings = new ConnectionSettings(new Uri("http://myesdomain.com:9200"));
var fieldResolver = new FieldResolver(connectionSettings);
var stringField = Infer.Field<MyDocument>(doc => doc.StringField1);
var fieldName = fieldResolver.Resolve(stringField);
Assert.Equal("stringField1", fieldName);
}
}
}

Asp.net-core api response WaitingForActivision

Can someone point me into the right direction what I am doing wrong in this Api call? I am getting an odd error that I don’t know what it means. The api call should work as I tested it using VBA and I get a response with the payload. Also any feedback is welcomed.
Id = 190, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}" - this is the response I am getting back from it
using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Xml.Linq;
namespace BarcodeScanner.Classes
{
public class Api : IDisposable
{
private readonly TimeSpan _timeout;
private HttpClient _httpClient;
private HttpClientHandler _httpClientHandler;
private readonly string _baseUrl;
private readonly string _credentials;
private const string MediaTypeXml = "application/xml";
public Api(string baseUrl, string authToken, TimeSpan? timeout = null)
{
_baseUrl = NormaliseBaseUrl(baseUrl);
_credentials = Base64Encode(authToken);
_timeout = timeout ?? TimeSpan.FromSeconds(90);
}
public async Task<string> GetAsync(string url)
{
EnsureHttpClientCreated();
using (var response = await _httpClient.GetAsync(url).ConfigureAwait(continueOnCapturedContext: false))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
public void Dispose()
{
_httpClientHandler?.Dispose();
_httpClient?.Dispose();
}
private void CreateHttpClient()
{
_httpClientHandler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
};
_httpClient = new HttpClient(_httpClientHandler, false)
{
Timeout = _timeout
};
if (!string.IsNullOrWhiteSpace(_baseUrl))
{
_httpClient.BaseAddress = new Uri(_baseUrl);
}
_httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + _credentials);
}
private void EnsureHttpClientCreated()
{
if (_httpClient == null)
{
CreateHttpClient();
}
}
//call the api
try
{
using (var client = new Api(requestUrl, authToken))
{
var response = client.GetAsync(requestUrl);
}
}
catch (Exception err)
{
throw new Exception("Something went wrong: ", err);
}

GraphQL is returning extra information which is slowing down the initial loading

I am getting some extra information within my graphql results.
Apart from the data and the end errors I am getting
document
operation
perf
extensions
so the result is getting quite bulky. The other think I've noticed is that the initial loading of the documents and the intellisens are taking ages to load.
Any idea how I can get rid of this additional data?
Result of the graphQL query:
GraphQL Controller
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ElectronConnectQuery.GraphQL;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace ElectronConnectQuery.Controllers.v1
{
[Route("[controller]")]
public class GraphQLController : Controller
{
private readonly IDocumentExecuter _documentExecuter;
private readonly ISchema _schema;
private readonly DataLoaderDocumentListener _listener;
private readonly ILogger<GraphQLController> _logger;
public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter, DataLoaderDocumentListener listener, ILogger<GraphQLController> logger)
{
_schema = schema;
_documentExecuter = documentExecuter;
_listener = listener;
_logger = logger;
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] GraphQLQuery query, [FromServices] IEnumerable<IValidationRule> validationRules)
{
if (query == null) { throw new ArgumentNullException(nameof(query)); }
_logger.LogDebug("GraphQL received query:{Query}", query.Query);
var inputs = query.Variables.ToInputs();
var executionOptions = new ExecutionOptions
{
Schema = _schema,
Query = query.Query,
Inputs = inputs,
ValidationRules = validationRules,
EnableMetrics = false
};
#if (DEBUG)
executionOptions.EnableMetrics = true;
#endif
executionOptions.Listeners.Add(_listener);
var result = await _documentExecuter.ExecuteAsync(executionOptions).ConfigureAwait(false);
if (result.Errors?.Count > 0)
{
return BadRequest(result);
}
return Ok(result);
}
}
}
Instead if writing the result yourself, use the IDocumentWriter, which will properly serialize the result.
/// <summary>
/// Serializes an object hierarchy to a stream. Typically this would be serializing an instance of the ExecutionResult class into a JSON stream.
/// </summary>
public interface IDocumentWriter
{
/// <summary>
/// Asynchronously serializes the specified object to the specified stream.
/// </summary>
Task WriteAsync<T>(Stream stream, T value, CancellationToken cancellationToken = default);
}
There is also an extension method to serialize to a string.
public static async Task<string> WriteToStringAsync<T>(this IDocumentWriter writer, T value)
This example shows using middleware vs. a controller but the idea is the same.
https://github.com/graphql-dotnet/examples/blob/529b530d7a6aad878b2757d776282fdc1cdcb595/src/AspNetCoreCustom/Example/GraphQLMiddleware.cs#L75-L81
private async Task WriteResponseAsync(HttpContext context, ExecutionResult result)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;
await _writer.WriteAsync(context.Response.Body, result);
}
You will need to include GraphQL.SystemTextJson or GraphQL.NewtonSoftJson to choose your implementation of IDocumentWriter.
https://www.nuget.org/packages/GraphQL.SystemTextJson
https://www.nuget.org/packages/GraphQL.NewtonsoftJson
The change which I've done to the controller is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using ElectronConnectQuery.GraphQL;
using GraphQL;
using GraphQL.DataLoader;
using GraphQL.Instrumentation;
using GraphQL.NewtonsoftJson;
using GraphQL.Types;
using GraphQL.Validation;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace ElectronConnectQuery.Controllers.v1
{
[Route("[controller]")]
public class GraphQLController : Controller
{
private readonly IDocumentExecuter _documentExecuter;
private readonly ISchema _schema;
private readonly DataLoaderDocumentListener _listener;
private readonly ILogger<GraphQLController> _logger;
private readonly IDocumentWriter _writer;
public GraphQLController(ISchema schema, IDocumentExecuter documentExecuter, DataLoaderDocumentListener listener, ILogger<GraphQLController> logger, IDocumentWriter writer)
{
_schema = schema;
_documentExecuter = documentExecuter;
_listener = listener;
_logger = logger;
_writer = writer;
}
[HttpPost]
public async Task Post([FromBody] GraphQLQuery query, [FromServices] IEnumerable<IValidationRule> validationRules)
{
if (query == null) { throw new ArgumentNullException(nameof(query)); }
_logger.LogDebug("GraphQL received query:{Query}", query.Query);
var inputs = query.Variables.ToInputs();
var executionOptions = new ExecutionOptions
{
Schema = _schema,
Query = query.Query,
Inputs = inputs,
ValidationRules = validationRules,
EnableMetrics = false,
};
executionOptions.Listeners.Add(_listener);
var result = await _documentExecuter.ExecuteAsync(opts =>
{
opts.Schema = _schema;
opts.Query = query.Query;
opts.Inputs = inputs;
opts.ValidationRules = validationRules;
opts.FieldMiddleware.Use<InstrumentFieldsMiddleware>();
opts.EnableMetrics = true;
}).ConfigureAwait(false);
result.EnrichWithApolloTracing(DateTime.Now);
await _writer.WriteAsync(Response.Body, result);
}
private async Task WriteResponseAsync(HttpResponse response, ExecutionResult result)
{
response.ContentType = "application/json";
response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK;
await _writer.WriteAsync(response.Body, result);
}
}
}
Startup.cs
In ConfigureServices
I have added the following lines
// kestrel
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
// IIS
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
Also I've registered the DocumentWriter
services.AddScoped<IDocumentWriter, GraphQL.NewtonsoftJson.DocumentWriter>();

Windows universal app isolated storage - How to save and retrieve data?

I have this isolated storage helper and I need to use it to save and retrieve data from my universal app.
I don't know where to begin from. Should I maybe make an app and incorporate the helper class into it?
Here is my class:
using System.IO;
//using System.IO.IsolatedStorage;
using System.Runtime.Serialization.Json;
using System.Text;
public static class IsolatedStorageHelper
{
public static T GetObject<T>(string key)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
if (localSettings.Values.ContainsKey(key))
{
string serializedObject = localSettings.Values[key].ToString();
return Deserialize<T>(serializedObject);
}
return default(T);
}
public static void SaveObject<T>(string key, T objectToSave)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
string serializedObject = Serialize(objectToSave);
localSettings.Values[key] = serializedObject;
}
public static void DeleteObject(string key)
{
var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
localSettings.Values.Remove(key);
}
private static string Serialize(object objectToSerialize)
{
using (MemoryStream ms = new MemoryStream())
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(objectToSerialize.GetType());
serializer.WriteObject(ms, objectToSerialize);
ms.Position = 0;
using (StreamReader reader = new StreamReader(ms))
{
return reader.ReadToEnd();
}
}
}
private static T Deserialize<T>(string jsonString)
{
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(ms);
}
}
}
use static SaveObject method and supply the 'person' entity and a key. Retrieve it later using GetObject.
But I think in this scenario you should use database sqlite and sqlite net package to save the entity.

Mock the business layer for integration testing the Web API

I want to do integration tests on my Web API without depending on my business layer interfaces.
When this action is run:
1) I want to mock the _service object and just verify that is is called
2) I want to assert that the correct StatusCode is returned
Number 2 is no problem but how can I mock the _service object (ISchoolyearService) when I do not control/start the creation of the api controller manually because this is a task done in unit testing the controller. But I do not want to unit test my API !
[RoutePrefix("api/schoolyears")]
public class SchoolyearController : ApiController
{
private readonly ISchoolyearService _service;
public SchoolyearController(ISchoolyearService service)
{
_service = service;
}
[Route("")]
[HttpPost]
public HttpResponseMessage Post([FromBody]SchoolyearCreateRequest request)
{
_service.CreateSchoolyear(request);
return Request.CreateResponse(HttpStatusCode.Created);
}
Following is a crude example of how you can do with in-memory integration testing. Here I am using Unity.WebApi.UnityDependencyResolver to inject mock dependencies. You can use any other IoC container similarly.
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using Unity.WebApi;
namespace WebApplication251.Tests.Controllers
{
[TestClass]
public class PeopleControllerTest
{
string baseAddress = "http://dummyhost/";
[TestMethod]
public void PostTest()
{
HttpConfiguration config = new HttpConfiguration();
// use the configuration that the web application has defined
WebApiConfig.Register(config);
//override the dependencies with mock ones
RegisterMockDependencies(config);
HttpServer server = new HttpServer(config);
//create a client with a handler which makes sure to exercise the formatters
HttpClient client = new HttpClient(new InMemoryHttpContentSerializationHandler(server));
SchoolyearCreateRequest req = new SchoolyearCreateRequest();
using (HttpResponseMessage response = client.PostAsJsonAsync<SchoolyearCreateRequest>(baseAddress + "api/schoolyears", req).Result)
{
Assert.IsNotNull(response.Content);
Assert.IsNotNull(response.Content.Headers.ContentType);
Assert.AreEqual<string>("application/json; charset=utf-8", response.Content.Headers.ContentType.ToString());
SchoolyearCreateRequest recSCR = response.Content.ReadAsAsync<SchoolyearCreateRequest>().Result;
//todo: verify data
}
}
private void RegisterMockDependencies(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterType<ISchoolyearService, MockSchoolyearService>();
config.DependencyResolver = new UnityDependencyResolver(unity);
}
}
[RoutePrefix("api/schoolyears")]
public class SchoolyearController : ApiController
{
private readonly ISchoolyearService _service;
public SchoolyearController(ISchoolyearService service)
{
_service = service;
}
[Route]
[HttpPost]
public HttpResponseMessage Post([FromBody]SchoolyearCreateRequest request)
{
_service.CreateSchoolyear(request);
return Request.CreateResponse(HttpStatusCode.Created);
}
}
public class InMemoryHttpContentSerializationHandler : DelegatingHandler
{
public InMemoryHttpContentSerializationHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Content = await ConvertToStreamContentAsync(request.Content);
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
response.Content = await ConvertToStreamContentAsync(response.Content);
return response;
}
private async Task<StreamContent> ConvertToStreamContentAsync(HttpContent originalContent)
{
if (originalContent == null)
{
return null;
}
StreamContent streamContent = originalContent as StreamContent;
if (streamContent != null)
{
return streamContent;
}
MemoryStream ms = new MemoryStream();
await originalContent.CopyToAsync(ms);
// Reset the stream position back to 0 as in the previous CopyToAsync() call,
// a formatter for example, could have made the position to be at the end
ms.Position = 0;
streamContent = new StreamContent(ms);
// copy headers from the original content
foreach (KeyValuePair<string, IEnumerable<string>> header in originalContent.Headers)
{
streamContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
return streamContent;
}
}
}

Resources