WebAPI in memory testing - getting error serialize IQueryable - asp.net-web-api

I have WebAPI implementation with method like this:
public IEnumerable<Device> GetAllDevices()
public Device GetDeviceById(int id)
Looks ok, it works when running in IIS or selfhosted. Returns JSON objects correctly.
However first method fails in my unit test where I attempt to use inmemory server.
System.InvalidOperationException : Cannot create and populate list type System.Linq.IQueryable`1[Test.Device].
This goes down to Newtonsoft.Json.Serialization assembly. An example of the test follow:
[Test]
public void GET_AskingForListOfDevices_GettingOk200WithListOfDevicesInJSON()
{
var client = new HttpClient(InMemoryServer);
HttpRequestMessage request = CreateRequest("api/devices", "application/json", HttpMethod.Get);
using (HttpResponseMessage response = client.SendAsync(request).Result)
{
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
Assert.NotNull(response.Content);
Assert.AreEqual("application/json", response.Content.Headers.ContentType.MediaType);
// next line throws exc
var content = response.Content.ReadAsAsync<IQueryable<Device>>().Result;
Assert.AreEqual(3, content.Count());
}
request.Dispose();
}
Any idea where to look?
UPDATE
The example below throws that error, however I found the solution to avoid it. Just by using IList<> instead of IQueryable<>. Still It does not answer me the question why it's working in Fiddler. Does it use the same trick?

I am running into same situation. IQueryable throws exception but if you use IEnumerable then it works.

Related

Find Error When Using Codec

I have a simple object named Tag that has an id, name, and three numeric properties. I also have a codec for the object. The folloing code executes without error.
MongoDatabase tagsDatabase =
usersProcess.getMongoClient().getDatabase(tagsDB)
.withCodecRegistry(usersProcess.getCodecRegistry());
MongoCollection<Tag> tagsCollection =
tagsDatabase.getCollection(tagsCollectionName, Tag.class);
ArrayList<Tag> tagsList = new ArrayList<Tag>();
FindIterable<Tag> tagsByAlpha =
tagsCollection.find().sort(Sorts.ascending("name"));
Following this, the code
tagsByAlpha.forEach(new Consumer<Tag>() {
#Override
public void accept(Tag t) {
tagsList.add(t);
}
});
thows the exception "org.bson.BsonInvalidOperationException: readEndArray can only be called when ContextType is ARRAY, not when ContextType is DOCUMENT" at the first line (forEach). An alternative construct
MongoCursor<Tag> tagsCursor = tagsByAlpha.iterator();
throws the same exception. It seems to be implying that find() has returned Documents rather than Tag objects. At the same time, the code that does work suggests that what I'm trying is possible. What am I doing wrong?
Should have used org.bson.codecs.DoubleCodec

How can use SSRS report inside UnitOfWork in aspnetboilerplate template?

Imagine there is a method in appservice which upgrade data and finally a report is made in Pdf form through Ssrs. All methods are unit of work, so data is not committed in server until calling method uow.CompleteAsync(). therefore GenerateSampleReport() can not be called. To solve the problem we have used [unit of work (Isdisabled = true) so the method is written so:
[UnitOfWork(IsDisabled =true)]
public async Task Method()
{
using (var uow = UnitOfWorkManager.Begin())
{
//some data manipulation
await uow.CompleteAsync();
}
var pdfFile GenerateSampleReport();
}
But, while providing the report, if there is any exception, report can not be generated and data manipulation must be roll backed(problem about data integrity). How to solve the problem?
you shouldn't begin your own Unit Of Work. And don't disable UnitOfWork. Normally if Method() is an application service method then this should work as you want.
public async Task Method()
{
//some data manipulation...
var pdfFile GenerateSampleReport();//if any exception occurs in this line, the db transaction will be rolled back.
}
have you checked this before?

using signalR .net core client

I have set up a signalR website .net core. My function in my hub is:
public async Task Notify(int id) {
await Clients.All.InvokeAsync("Notified", id);
}
I have also tested this with the following js:
let connection = new signalR.HubConnection(myURL);
connection.on('Notified', data => {
console.log(4, data);
});
connection.start();
The js code seems to work fine and I see the log when I try connection.Invoke('Notify').
Now I have a console app that can needs to make the invoke. I am trying this in two ways and don't mind either solution:
1. A mvc controller within the signalR website that can take the id and invoke 'Notified'.
2. Use the client library Microsoft.AspNetCore.SignalR.Client in the console app.
The way 1 I have only done in classic asp.net like this:
GlobalHost.ConnectionManager.GetHubContext(hubName)
But couldn't find a way to do this in .net core.
Way 2 I have used the library and tried this so far:
var con = new HubConnectionBuilder();
con.WithUrl(myURL);
var connection = con.Build();
connection.InvokeAsync("Notify",args[0]).Wait();
This is the closest I have come to create a connection in the same way as the js code. However this code throws a null pointer when calling connection.InvokeAsync. The connection object is not null. It seems to be an internal object that is null. According to the stack trace the exception is thrown when a MoveNext() function is internally called.
Well looks like both are not currently possible. As of now I just used a forced way which is hopefully temporary.
I have created and used the following base class for hubs:
public abstract class MyHub : Hub
{
private static Dictionary<string, IHubClients> _clients = new Dictionary<string, IHubClients>();
public override Task OnConnectedAsync()
{
var c = base.OnConnectedAsync();
_clients.Remove(Name);
_clients.Add(Name, Clients);
return c;
}
public static IHubClients GetClients(string Name) {
return _clients.GetValueOrDefault(Name);
}
}
GlobalHost is gone. You need to inject IHubContext<THub> like in this sample.
This can be a bug in SignalR alpha1. Can you file an issue on https://github.com/aspnet/signalr and include a simplified repro?

Amazon IAP Plugin for Xamarin - crash when using TaskCompletionSource

I'm trying to implement a wrapper for the Amazon IAP Plugin for Xamarin. It uses an event based system in the following way:
You can initiate method calls and listen for events. Method calls initiate requests, some of which return a response. Events are asynchronous system-generated messages that are sent in response to method calls to return the requested data to you.
See more here
My goal is to wrap this event based system into some API which allows me to use the plugin with tasks, so I can use the async-await syntax. To achieve that I'm using the TaskCompletionSource like in the following example:
public async Task<bool> GetProductInfoAsync(params string[] productIds)
{
var iapService = AmazonIapV2Impl.Instance;
var tcs = new TaskCompletionSource<bool>();
var skus = new SkusInput { Skus = productIds.ToList() };
var requestId = iapService.GetProductData(skus).RequestId;
GetProductDataResponseDelegator delegator = null;
delegator = new GetProductDataResponseDelegator(response =>
{
if(response.Id == requestId) {
var result = GetResultFromResponse(response);
tcs.SetResult(result);
//iapService.RemoveGetProductDataResponseListener(delegator.responseDelegate);
}
});
iapService.AddGetProductDataResponseListener(delegator.responseDelegate);
return await tcs.Task;
}
This code seems to work fine if the method gets called once, but if it gets called two times in a row the app crashes immediately and the only thing printed to the console is the following message..
[mono] Unhandled Exception:
[mono] System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
[mono-rt] [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
..which kinda makes no sense at all.
So is there something obvious I'm missing here? Or could it be a bug from the plugin?
I have created a repository with the code above so you can reproduce the problem. It's my playground, so please ignore the whole structure of the project and just focus on the classes AmazonIAPService and MainActivity.
Hint 1:
The commented line //iapService.RemoveGetProductDataResponseListener(delegator.responseDelegate); causes also a crash with the same message but already at the first call of the method.
Hint 2:
The AmazonIAPService contains a commented method which uses await Task.Delay(TimeSpan.FromMilliseconds(1)) and solves the problem from above in a very hacky way which I really don't like.
Problem seems to be that those functions have to run asynchronously. Also mentioned here in the doc. So once you run those functions synchronously somehow they throw exception, i dont what is happening in the library but your hacky solution is the actual solution for that. If you write the function as below. it also works.
PurchaseResponseDelegator delegator = null;
delegator = new PurchaseResponseDelegator(async response =>
{
await Task.Run(() =>
{
if (response.RequestId == requestId)
{
var result = GetPurchaseEventHandler(response);
var sucess = taskCompletionSource.TrySetResult(result);
context.RemovePurchaseResponseListener(delegator.responseDelegate);
}
} );
});
// Register for an event
context.AddPurchaseResponseListener(delegator.responseDelegate);
One other exception I had despite the async-await solution, somehow, it always throws exception for the line taskCompletionSource.SetResult(result); for PurchaseUpdates functions only. if i use instead this line var sucess = taskCompletionSource.TrySetResult(result); it works fine

Return an object and control status code

I upgraded from the ASP.NET Web API release on nuget.org (the version before the RC on Friday) to the nightly builds on myget.org. As expected there were many breaking changes, and one of them I can't seem to get around: We have a scenario where we want our action to return an object and set the status code to 201 Created. This was quite easily done before (might not compile - conceptual code from the top of my head):
Session session = GetSessionInfo(requestMessage);
var response = new HttpResonseMessage(HttpStatusCode.Created);
response.Content = response.CreateContent(session);
return response;
CreateContent was actually an extension method located in System.Net.Http.HttpResponseMessageExtensions calling an internal constructor in ObjectContent. With the new release HttpResponseMessageExtensions seems to be gone in the new release and so does the internal constructors of ObjectContent. Now it seems I must call an ObjectContent constructor, and the following seems to be the most appropriate for our needs:
public class ObjectContent<T> : ObjectContent
{
public ObjectContent(T value, MediaTypeFormatter formatter)
{
}
}
However it seems I have to pass a MediaTypeFormatter into it, mixing content negotiation into the logic of the action. In our setup content negotiation is generic and completely decoupled from the controllers.
Does anyone have a suggestion for solving the scenario to return an object, set the response status code, but not have to deal with MediaTypeFormatter, media type or any other content negotiation related stuff?
We redesigned how ObjectContent<T> creation works. Starting with the RC, you should be calling the CreateResponse() set of extension methods (they're off HttpRequestMessage). This will actually produce an instance of HttpResponseMessage with an instance of a content-negotiated ObjectContent<T> inside. So, something like:
Session session = GetSessionInfo(requestMessage);
var response = Request.CreateResponse(HttpStatusCode.Created, session);
return response;

Resources