using System.Threading.Tasks;
using System.Web.Http;
using EdgeJs;
namespace edge2.Controllers
{
public class ValuesController : ApiController
{
public async Task<object> Get(int id)
{
var func = Edge.Func(#"
return function (data, callback) {
callback(null, 'Node.js welcomes ' + data);
}
");
return await func(".NET");
}
}
}
I'm looking at trying to call node.js from C#. I have the above example code that is documented on their GitHub page, but when the code is moved over to a C# Web API project I get a consistent error.
AccessViolation Exception. The error only happens on the first run, and only after a rebuild of the project. All subsequent runs work perfectly.
Tooling:
VS2015
.NET 4.5.2
EdgeJS 4.0.0
Related
We have the following mixed-environment scenario (Azure and LAN):
Azure Web App calls a method in the Azure API (triggered by some user action in the web app).
This Azure API then establishes a SignalR HubContext connection .
The HubContext broadcasts a message.
The SignalR client (consuming the message) is a Windows Service installed on a machine on the LAN, behind the firewall.
Our client is complaining that the connection often breaks, and therefore several messages are missing on a daily basis.
Here is a test method in the Azure API, which attempts to broadcast a message:
using Microsoft.AspNet.SignalR;
using System;
using System.IO;
using System.Net.Http.Headers;
using System.Reflection;
using System.Runtime.Caching;
using System.Text;
using System.Web.Http;
using System.Xml;
...
namespace MyTestAPI.Controllers
[AllowCrossSiteJson]
[RoutePrefix("api/Test")]
public class HL7Controller : ApiController
[HttpGet]
[Route("TestSignalR")]
public IHttpActionResult TestSignalR()
{
string reportData = $"<TestReport>This is a test message generated on { DateTime.Now }.</TestReport>";
var hubContext = GlobalHost.ConnectionManager.GetHubContext<HL7Hub>();
hubContext.Clients.All.SendReportData(reportData);
return Ok(reportData);
}
...
}
And in the client's environment, there's a Win Service installed - it acts as the SignalR Client
And here's a snippet of our H..NotificationsService solution (vs2019, Framework 4.6.1)
using log4net.Ext.EventID;
using Microsoft.AspNet.SignalR.Client;
using System;
using System.Configuration;
using System.Diagnostics;
using System.Net;
using System.ServiceProcess;
using System.Threading;
namespace H_NotificationSrv
{
public partial class H_NotificationService : ServiceBase
public async void StartListner()
{
try
{
var hubConnection = new HubConnection(hl7APIUrl);
hubConnection.Credentials = CredentialCache.DefaultNetworkCredentials;
var hubProxy = hubConnection.CreateHubProxy("MyTestHub");
hubProxy.On<string>("SendReportData", reportData =>
{
SendReportDataToSomeone(reportData);
});
await hubConnection.Start();
}
catch (Exception ex)
{
string errorMessage = ex.Message;
if (ex.InnerException != null)
errorMessage += " Inner Exception: " + ex.InnerException.Message;
applog.Error(errorMessage);
}
}
}
}
I'm trying to create a service that does absolutely nothing for testing purposes. For that I need a binary that does absolutely nothing but services don't seem to start for just any executable, only ones specifically designed to be service binaries. I've tried to find information as to how to make service binaries but can't seem to find anything. Thanks in advance.
Check out the demo service in this little nuget library:
https://github.com/wolfen351/windows-service-gui
It should give you a good starting point for making a test service to use, it is a trivial implementation of a windows service that does nothing. Also the nuget package will help you run it! :)
Here is the heart of the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
namespace DemoService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
Timer t1 = new Timer(AutoStopCallback, null, 15000, -1); // auto stop in 15 seconds for testing
}
private void AutoStopCallback(object state)
{
Stop();
}
protected override void OnStart(string[] args)
{
Thread.Sleep(2000);
base.OnStart(args);
}
protected override void OnStop()
{
Thread.Sleep(2000);
base.OnStop();
}
protected override void OnContinue()
{
Thread.Sleep(2000);
}
protected override void OnPause()
{
Thread.Sleep(2000);
}
}
}
I get error "The parameter 'wheels' is of Edm type kind 'Collection'.
You cannot call CreateCollectionWriter on a parameter that is not of
Edm type kind 'Collection'."
Below are details of my setup:
Web API 2.2 OData v4 service : I have defined Action in WheelsController class in my service like this:
public async Task<IHttpActionResult> UpdateWheels(ODataActionParameters parameters)
{
object value;
parameters.TryGetValue("carId", out value);
int carId= (int)value;
parameters.TryGetValue("wheels", out value)
IEnumerable<Wheel> wheels = (IEnumerable<Wheel>)value;
// logic goes here....
return OK();
}
In WebApiConfig.cs files, the Action configuration is defined as below:
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Car>("Cars");
builder.EntitySet<Wheel>("Wheels");
var action = builder.EntityType<Wheel>().Collection.Action("UpdateWheels");
action.Parameter<int>("carId");
action.CollectionParameter<Wheel>("wheels");
I get success in invoking the above action from RESTClient extenstion in FireFox browser as POST request to URL "http://localhost/Service/Wheels/UpdateWheels" with Request Body as
{"carId":2,
"wheels":[{"Id":1,"Name":"Wheel Front 1","Description":"Front wheel left", "PositionEnum":"FrontLeft"},
{"Id":2,"Name":"Wheel Front 2","Description":"Front wheel right", "PositionEnum":"FrontRight"}]
}
However, it gives error when I try to invoke the above service action using Simple.OData.Client in client application such as
public async void TestUpdateWheels(List<Wheel> wheelList)
{
// client is derived from ODataClient from assembly Simple.OData.Client.Core.dll, v4.3.0.0
await client.For<Wheel>()
.Action("UpdateWheels")
.Set(new { carId = 2, wheels = wheelList})
.ExecuteAsync();
}
Error message: The parameter 'wheels' is of Edm type kind
'Collection'. You cannot call CreateCollectionWriter on a parameter
that is not of Edm type kind 'Collection'.
How can I call successfully the above Action from ODataClient?
This turn out to be a bug in Simple.OData.Client version 4.3.0 when I reported to the project site. For details, visit the link https://github.com/object/Simple.OData.Client/issues/117
The new bug fix version 4.7.2 of Simple.OData.Client has fixed the
issue for me!
Try out in this way. It works for me in one of my project.
public async Task<string> TestUpdateWheels(List<Wheel> wheelList)
{
string getRules = await client.ExecuteActionAsScalarAsync<string>
("UpdateWheels", new Dictionary<string, object>
{
{ "YourParamater", wheelList}
});
return getRules ;
}
I am attempting to use an asp web api to populate an html table using angular. everything works great if I debug in firefox (I'm assuming because my web service is being returned in json) however in ie and chrome it does not load (the web service returns xml in these browsers). In the webapiconfig I attempted to always make the service return json by adding.
Dim appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(Function(t) t.MediaType = "application/xml")
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType)
this appears to work when I navigate to the api in all browsers it is returning json however the $http get is still now working in chrome and ie.
in ie I get the following error
Unhandled exception at line 21, column 406 in http://localhost:53175/Scripts/angular.min.js
0x800a139e - JavaScript runtime error: [$injector:nomod] http://errors.angularjs.org/1.3.13/$injector/nomod?p0=api%2Fproducts
here is my get
angular.module("api/products").constant("dataUrl", "sportstore.json").controller("sportsStoreCtrl", function ($scope, $resource, dataUrl) {
$scope.data = {};
var resultPromise = $resource(dataUrl);
resultPromise.success(function (data) {
$scope.data.products = data;
})
});
any thoughts?
additional info
here is my api controller
<pre>
Imports System.Net
Imports System.Web.Http
Imports apitoform.productRepository
Namespace Controllers
Public Class productController
Inherits ApiController
Private repo As productRepository = productRepository.Current
Public Function GetAllProducts() As IEnumerable(Of product)
Return repo.GetAll()
End Function
End Class
End Namespace
</pre>
and here is the j_son that is being returned ( I am working through the pro Angular book if it looks familiar)
Sorry this is c# code, but it should illustrate the basic idea for returning Json only from web api. It's actual code from one of my projects.
[Route("api/users/getbyemail/")]
public HttpResponseMessage GetByEmail(string email)
{
try
{
var result = _userService.GetByEmail(email);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
response.Content = new ObjectContent(typeof(IEnumerable<UserViewModel>), result ?? new List<UserViewModel>(), new JsonMediaTypeFormatter());
response.Headers.Add("Access-Control-Allow-Origin", "*");
return response;
}
catch (Exception ex)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
response.Headers.Add("Access-Control-Allow-Origin", "*");
return response;
}
}
So you are returning HttpResponseMessage with Json content.
I'm also doing similar in a scenario where I just need to return the data from one of the MVC controllers and that is even easier:
public ActionResult Get(string guid)
{
var profileVm = _profileService.Get(guid);
if (profileVm != null)
{
return Json(profileVm, JsonRequestBehavior.AllowGet);
}
return new HttpNotFoundResult();
}
angular.module with 1 parameter returns the module with that name - you need to define your module with a list of dependent modules (or empty array if none) like the following:
angular.module("api/products", [])...
The error referenced gives an error with details on the problem (angular's very good about their error messages): https://docs.angularjs.org/error/$injector/nomod?p0=api%2Fproducts
I have a custom ActionResult that sets HttpResponse.BufferOutput = false and then writes data to the response stream. I noticed that when the action result comes from a task-based asynchronous action method in ASP.NET MVC, writing to the response stream blocks. This happens only when Glimpse plugin is enabled in web.config. Glimpse is very useful to me, I really want to have it enabled, at least during development and testing. BufferOutput property should remain false, because the content length can be quite large and I don't want to buffer it in memory.
This is the shortest code that could reproduce this exact behaviour:
public sealed class CustomResult : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
var resp = context.HttpContext.Response;
resp.BufferOutput = false;
resp.ContentType = "text/plain";
resp.Output.Write(DateTime.UtcNow.ToString());
resp.Flush();
}
}
public sealed class DownloadController : Controller
{
// the client nevers gets the response from this action
public async Task<ActionResult> Async()
{
await Task.Yield();
return new CustomResult();
}
// this works
public ActionResult Sync()
{
return new CustomResult();
}
}
I tested this with the latest Glimpse.Mvc4 package (version 1.3.2).
Am I doing something wrong, is there a workaround to this issue or is this a Glimpse bug and I should report it?