There are two type of constructors I can call to initialise the Sqlite connection. I know SQLiteAsyncConnection is to create an async method when execute the sql statement whereas SQLiteConnection is for normal method.
If I have a method like below:
public object InsertVeggie(string name)
{
lock (locker) {
var sql = "Some query ?";
var result = database.Query<Model>(sql, name);
return result;
}
}
If I have an async method:
public async Task<Model> GetModel (string name)
{
var data = InsertVeggie(name);
await ProcessVeggie(data);
return data;
}
Calling method :
Task.Run (async () =>
{
var result1 = await GetModel("124");
});
Task.Run (async () =>
{
var result2 = await GetModel("335");
});
If I use SQLiteConnection instead of SQLiteAsyncConnection, will there be an issue or have to change the InsertVeggie to Async method as well.
As you say, SQLiteAsyncConnection exposes asynchronous methods so you would typically consume them from your own async methods.
Your InsertVeggie method would change to:
public async Task<object> InsertVeggie(string name)
{
var sql = "Some query ?";
var result = await database.QueryAsync<Model>(sql, name);
return result;
}
(note you no longer need the lock), and you would consume it as:
var data = await InsertVeggie(name);
Related
I have an endpoint that subscribes the specified email to my SNS topic:
[HttpPost("subscriptions/{email}")]
public async Task SubscribeEmail(string email)
{
try
{
var request = new SubscribeRequest()
{
TopicArn = AwsServicesConstants.SenderTopicArn,
ReturnSubscriptionArn = true,
Protocol = "email",
Endpoint = email,
};
var response = await _snsClient.SubscribeAsync(request);
}
catch (Exception ex)
{
Console.WriteLine($"Unexpected error: {ex}");
}
}
How can I unsubscribe given email from that topic with just a specified email like this
[HttpDelete("subscriptions/{email}")]
public async Task<UnsubscribeResponse> UnsubscribeEmail(string email)
{
var request = new UnsubscribeRequest(email);
var response = await _snsClient.UnsubscribeAsync(request);
return response;
}
Actually, unsubscription is not working because UnsubscribeRequest requires only subscriptionArn, and not the email
You will need to identify the subscription (once subscribed) by calling ListSubscriptionsByTopic, looking for the Endpoint that matches the desired email address. You could then extract the ARN and use it when calling Unsubscribe.
You can write app logic to get the ARN value using the email address. Here is a C# example that shows you the logic for this use case using the AWS SDK for .NET.
public async Task<string> UnSubEmail(string email)
{
var client = new AmazonSimpleNotificationServiceClient(RegionEndpoint.USEast2);
var arnValue = await GetSubArn(client, email);
await RemoveSub(client, arnValue);
return $"{email} was successfully deleted!";
}
public static async Task<string> GetSubArn(IAmazonSimpleNotificationService client, string email)
{
var request = new ListSubscriptionsByTopicRequest();
request.TopicArn = TopicArn;
var subArn = string.Empty;
var response = await client.ListSubscriptionsByTopicAsync(request);
List<Subscription> allSubs = response.Subscriptions;
// Get the ARN Value for this subscription.
foreach (Subscription sub in allSubs)
{
if (sub.Endpoint.Equals(email))
{
subArn = sub.SubscriptionArn;
return subArn;
}
}
return string.Empty;
}
public static async Task<string> RemoveSub(IAmazonSimpleNotificationService client, string subArn)
{
var request = new UnsubscribeRequest();
request.SubscriptionArn = subArn;
await client.UnsubscribeAsync(request);
return string.Empty;
}
You can find full .NET Example in the AWS Code Lib:
Build a publish and subscription application that translates messages
I have an asmx Web Service and I am using async Task. My problem is whenever I reached on the PostAsync statement it will just end there and fire a result to the browser with an empty result. Which is not I want. I tried passing the httpclient as a parameter to my service class thinking it may solved the issue.
I tried putting ConfigureAwait(false) and it gives a result however I don't want this because I need to return the value to the user. If I use ConfigurAwait(false) it will return an empty result to the browser even if it it still not completed. Am I doing this right? Thanks
in my webmethod
public class WebService1 : WebService
{
HttpClient Client = new HttpClient();
XDocument doc = new XDocument();
[WebMethod]
private async Task<String> Sample1(string a, int b)
{
myServiceClass _ms = new myServiceClass(Client);
var message = await _ms.GetResponseMessageAsync(a,b);
doc = await _ms.ReadResponseAsync(message); // It will not reach here if I don't use ConfigureAwait(false)
return JsonConvert.SerializeObject(doc);
}
}
myServiceClass.cs
public class myServiceClass
{
HttpClient _client;
public myServiceClass(HttpClient client)
{
_client = client;
}
public async Task<HttpResponseMessage> GetResponseMessageAsync(string a, int b)
{
HttpResponseMessage message;
httpcontent = (a,encoding.UTF8,"text/xml"); //This is just a sample content
message = await _client.PostAsync(UrlString, httpcontent); //<= here it stops and return empty result if there is no ConfigureAwait(false).
if (!message.IsSuccessStatusCode)
{
throw new HttpRequestException($"Cannot connect to api: {message.StatusCode} , {message.ReasonPhrase}");
}
return message; // It will not reach here if I don't use ConfigureAwait(false)
}
}
I have a requirement to implement paging on api. Am doing below to enable OData querying on api, but it filters after fetching all records from cosmos db, but I would like to fetch filtered records from cosmos db. How to convert Odata query options to cosmos db query options?
controller.cs
[Route("apps")]
[HttpGet]
[EnableQuery]
public async Task<IActionResult> GetAllApps(CancellationToken cancellationToken)
{
var user = this.GetUser();
var results = await this.appRepository.GetAppsForUserAsync(user, cancellationToken).ConfigureAwait(false);
return this.Ok(this.mapper.Map<AppHeader[]>(results));
}
AppRepository.cs
public async Task<IEnumerable<App>> GetAppsForUserAsync(User user, CancellationToken cancellationToken)
{
try
{
FeedOptions queryOptions = new FeedOptions
{
MaxItemCount = -1,
PartitionKey = new PartitionKey(user)
};
var query = this.factory.GetClient()
.CreateDocumentQuery<App>(
UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName),
queryOptions)
.Where(resource => resource.UserList.Any(u => u.userId == user.Id))
.AsDocumentQuery();
List<App> results = new List<App>();
while (query.HasMoreResults)
{
cancellationToken.ThrowIfCancellationRequested();
var response = await query.ExecuteNextAsync<App>(cancellationToken).ConfigureAwait(false);
var app = this.mapper.Map<App[]>(response);
results.AddRange(app);
}
return results;
}
catch (DocumentClientException ex)
{
this.logger.LogError(ex, ex.Message);
throw;
}
}
Client.js
http://localhost:8303/api/appdefinitions/my?$skip=6&$top=4`
In the repository, try using GetItemLinqQueryable and query on that. Note I am using newer V3 SDK Microsoft.Azure.Cosmos here, but equivalent should exist in older SDK too.
// Take `skip` and `top` params as input to the repository method.
List<App> results = new List<App>();
using (CosmosClient client = new CosmosClient(endpoint, authKey))
{
Database cosmosDatabase = await client.CreateDatabaseIfNotExistsAsync(DatabaseName);
Container container = await Program.GetOrCreateContainerAsync(cosmosDatabase, CollectionName);
// LINQ query generation
using (FeedIterator setIterator = container.GetItemLinqQueryable<App>()
.Where(a => a.userId == user.Id)
.Skip(skip)
.Take(top)
.ToFeedIterator())
{
//Asynchronous query execution
while (setIterator.HasMoreResults)
{
var items = await feedIterator.ReadNextAsync().ConfigureAwait(false);
results.AddRange(items);
}
}
}
NOTE: Ideally in real application you should reuse CosmosClient instance instead of creating every time for performance improvement.
I'm using async / await methods in C#... my operations are to create databases on Azure Cosmos DB, the problem is when the code is runnnig, for any reason... the flow brakes without any issues apparently
can anyone help?
Task p= Run();
public async static Task Run()
{
.
.
.
await CreateDatabase(client)
}
private async static Task CreateDatabase(DocumentClient client)
{
var databaseDefinition = new Database { Id = "MyDB" };
var result = await client.CreateDatabaseAsync(databaseDefinition);
var database = result.Resource;
}
//In second line, the code brake when the debugging is operating
//==> var result = await client.CreateDatabaseAsync(databaseDefinition);
Lets say I am setting a value on the http context in my middleware. For example HttpContext.User.
How can test the http context in my unit test. Here is an example of what I am trying to do
Middleware
public class MyAuthMiddleware
{
private readonly RequestDelegate _next;
public MyAuthMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
context.User = SetUser();
await next(context);
}
}
Test
[Fact]
public async Task UserShouldBeAuthenticated()
{
var server = TestServer.Create((app) =>
{
app.UseMiddleware<MyAuthMiddleware>();
});
using(server)
{
var response = await server.CreateClient().GetAsync("/");
// After calling the middleware I want to assert that
// the user in the HttpContext was set correctly
// but how can I access the HttpContext here?
}
}
Following are two approaches you could use:
// Directly test the middleware itself without setting up the pipeline
[Fact]
public async Task Approach1()
{
// Arrange
var httpContext = new DefaultHttpContext();
var authMiddleware = new MyAuthMiddleware(next: (innerHttpContext) => Task.FromResult(0));
// Act
await authMiddleware.Invoke(httpContext);
// Assert
// Note that the User property on DefaultHttpContext is never null and so do
// specific checks for the contents of the principal (ex: claims)
Assert.NotNull(httpContext.User);
var claims = httpContext.User.Claims;
//todo: verify the claims
}
[Fact]
public async Task Approach2()
{
// Arrange
var server = TestServer.Create((app) =>
{
app.UseMiddleware<MyAuthMiddleware>();
app.Run(async (httpContext) =>
{
if(httpContext.User != null)
{
await httpContext.Response.WriteAsync("Claims: "
+ string.Join(
",",
httpContext.User.Claims.Select(claim => string.Format("{0}:{1}", claim.Type, claim.Value))));
}
});
});
using (server)
{
// Act
var response = await server.CreateClient().GetAsync("/");
// Assert
var actual = await response.Content.ReadAsStringAsync();
Assert.Equal("Claims: ClaimType1:ClaimType1-value", actual);
}
}
The RC1 version of asp.net 5/MVC6 makes it possible to set HttpContext manually in Unit Tests, which is awesome!
DemoController demoController = new DemoController();
demoController.ActionContext = new ActionContext();
demoController.ActionContext.HttpContext = new DefaultHttpContext();
demoController.HttpContext.Session = new DummySession();
DefaultHttpContext class is provided by the platform.
DummySession can be just simple class that implements ISession class. This simplifies things a lot, because no more mocking is required.
It would be better if you unit test your middleware class in isolation from the rest of your code.
Since HttpContext class is an abstract class, you can use a mocking framework like Moq (adding "Moq": "4.2.1502.911", as a dependency to your project.json file) to verify that the user property was set.
For example you can write the following test that verifies your middleware Invoke function is setting the User property in the httpContext and calling the next middleware:
[Fact]
public void MyAuthMiddleware_SetsUserAndCallsNextDelegate()
{
//Arrange
var httpContextMock = new Mock<HttpContext>()
.SetupAllProperties();
var delegateMock = new Mock<RequestDelegate>();
var sut = new MyAuthMiddleware(delegateMock.Object);
//Act
sut.Invoke(httpContextMock.Object).Wait();
//Assert
httpContextMock.VerifySet(c => c.User = It.IsAny<ClaimsPrincipal>(), Times.Once);
delegateMock.Verify(next => next(httpContextMock.Object), Times.Once);
}
You could then write additional tests for verifying the user has the expected values, since you will be able to get the setted User object with httpContextMock.Object.User:
Assert.NotNull(httpContextMock.Object.User);
//additional validation, like user claims, id, name, roles
take a look at this post:
Setting HttpContext.Current.Session in a unit test
I think what you need is this.
public static HttpContext FakeHttpContext(string url)
{
var uri = new Uri(url);
var httpRequest = new HttpRequest(string.Empty, uri.ToString(),
uri.Query.TrimStart('?'));
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var httpContext = new HttpContext(httpRequest, httpResponse);
var sessionContainer = new HttpSessionStateContainer("id",
new SessionStateItemCollection(),
new HttpStaticObjectsCollection(),
10, true, HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);
SessionStateUtility.AddHttpSessionStateToContext(
httpContext, sessionContainer);
return httpContext;
}
Then you can use it like:
request.SetupGet(req => req.Headers).Returns(new NameValueCollection());
HttpContextFactory.Current.Request.Headers.Add(key, value);