Topshelf: Issues using NancyFX with Topshelf 4.2.1 - nancy

I am trying to develop a data access service using Visual Studio 2019, .Net Core 3.0. I am using NancyFX to handle http requests. this is working just fine as a console application. When I build and run, then in browser go to HTTP://localhost/, it returns the proper data. I have a working Nancy module to handle requests. Here is original Main code:
static void Main(string[] args)
{
Logger.LogInfo("NancyDataService starting...");
var uri = new Uri(ConfigurationManager.AppSettings["uri"]);
var hostConfig = new HostConfiguration();
hostConfig.UrlReservations.CreateAutomatically = true;
hostConfig.RewriteLocalhost = false;
using (var nancyHost = new NancyHost(uri, new AppBootstrapper(), hostConfig))
{
try
{
nancyHost.Start();
Console.WriteLine($"Nancy now listening on {uri}.\n\nPress any key to exit");
Logger.LogInfo($"Nancy now listening on {uri}...");
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
Console.WriteLine("Error " + ex.Message + "\n\nPress any key to exit");
}
Console.ReadKey();
Logger.LogInfo("NancyDataService stopped...");
}
}
Now I want to make it a Windows Service. First try is with Topshelf. The following Main code is basically taken from Topshelf documentation and other articles about Topshelf.
static void Main(string[] args)
{
Logger.LogInfo("NancyDataService starting...");
var rc = HostFactory.Run(x =>
{
x.Service<DataService>(s =>
{
s.ConstructUsing(name => new DataService());
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.StartAutomatically();
x.EnableServiceRecovery(r => r.RestartService(TimeSpan.FromSeconds(10)));
x.SetServiceName("NancyDataService");
});
var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode()); //11
Environment.ExitCode = exitCode;
}
Here is my DataService class, basically built from the Topshelf docs and a couple of articles I found:
class DataService
{
public DataService()
{
}
private SemaphoreSlim _semaphoreToRequestStop;
private Thread _thread;
public void Start()
{
// start Nancy here
var uri = new Uri(ConfigurationManager.AppSettings["uri"]);
var hostConfig = new HostConfiguration();
hostConfig.UrlReservations.CreateAutomatically = true;
hostConfig.RewriteLocalhost = false;
using var nancyHost = new NancyHost(uri, new AppBootstrapper(), hostConfig);
try
{
nancyHost.Start();
Console.WriteLine($"Nancy now listening on {uri}...");
Logger.LogInfo($"Nancy now listening on {uri}...");
// spin thread here
_semaphoreToRequestStop = new SemaphoreSlim(0);
_thread = new Thread(DoWork);
_thread.Start();
}
catch (Exception ex)
{
Logger.LogError(ex.Message);
Console.WriteLine($"Error: {ex.Message}");
}
}
private void DoWork(object obj)
{
while (true)
{
Console.WriteLine("doing work..");
if (_semaphoreToRequestStop.Wait(500))
{
Console.WriteLine("Stopped");
break;
}
}
}
public void Stop()
{
Logger.LogInfo("NancyDataService stopping...");
_semaphoreToRequestStop.Release();
_thread.Join();
//return true;
}
}
So now when I run the project in design mode (which Topshelf says you should be able to do), it seems to start fine and Nancy seems to be listening on the right port. However, when I go to the browser and type in HTTP//localhost:8080/, I get "This site can't be reached. localhost refused to connect"
I have the latest version of Topshelf (4.2.1) and Topshelf.Log4Net packages.
Can anyone shed any light on this? Thanks...

Solved this issue. Turned out to be incorrect scoping of my NancyHost object. Works fine now.

Related

WebView2 not initializing

I created a simple WPF client app in .net6.0 and incorporated WebView2 control.
I deployed/copied this app to a different machine and also installed .NET6.0 runtime there.
Upon running this app, I only see the main window and NO WebView2 initialized/created.
Note this the same implementation is working on my dev machine.
public MainWindow()
{
InitializeComponent();
InitializeWebView2();
}
private async Task InitializeWebView2()
{
//myPanel.Children.Add(webView2);
//await webView2.EnsureCoreWebView2Async();
((Action)(async () =>
{
try
{
CoreWebView2Environment env = await CoreWebView2Environment.CreateAsync(null, "another_dir");
WebView2 webview = new WebView2();
/*
webview.Source = new Uri("https://www.bing.com");
*/
var result = webview.EnsureCoreWebView2Async(env).GetAwaiter();
result.OnCompleted(() =>
{
try
{
result.GetResult();
}
catch (Exception e)
{
Console.WriteLine(e);
}
});
myPanel.Children.Add(webview);
webview.NavigateToString("https://google.com");
}
catch (Exception e)
{
Console.WriteLine(e);
}
})).Invoke();
}
EnsureCoreWebView2Async is supposed to be awaited before you set the Source:
private async Task InitializeWebView2()
{
var webview = new WebView2();
myPanel.Children.Add(webview);
var env = await CoreWebView2Environment.CreateAsync(null, "another_dir");
var result = await webview.EnsureCoreWebView2Async(env);
webview.Source = new Uri("https://www.bing.com");
}

Codename One WebSocket + Spring Boot

About the Codename One Websocket cn1lib, I saw your lesson on the Whatsapp clone, however the code you proposed is for a complete app. Could you provide a simpler self-enclosed example of use of Websocket cn1lib with client-side code (Codename One code to send and receive messages) and server-side code (Spring Boot Java 8 to receive and send messages)?
I’m particulary interested in a simple Spring Boot example that interacts with Codename One, as start point to better understand and learn websocket.
Thank you
It would look roughly like this on the server:
public class WebSocketServer extends TextWebSocketHandler {
private static final Object LOCK = new Object();
private Map<String, WebSocketSession> sessions = new HashMap<>();
#Override
protected void handleTextMessage(WebSocketSession session,
TextMessage message) throws Exception {
Gson gson = new Gson();
MyDTO parsed = gson.fromJson(message.getPayload(), MyDTO.class);
// ... do stuff with incoming message
synchronized(LOCK) {
if(!sessions.contains(parsed.getId()) {
sessions.put(parsed.getId(), session);
}
}
}
public boolean sendMessage(String destId, String json) {
Session s = null;
synchronized(LOCK) {
s = sessions.get(destId);
}
if (s != null && s.isOpen()) {
try {
s.sendMessage(new TextMessage(s));
return true;
} catch (IOException e) {
synchronized(LOCK) {
sessions.remove(destId);
}
}
}
return false;
}
}

PostgreSQL and Blazor .Net Core 3.1

Are there any resources on how to use the current version of Blazor (3.1) and PostgreSQL?
I've tried writing the simplest code, just to see whether it connects to the database but I get this error message: System.Net.Dns:GetHostByName is not supported on this platform
a button click would activate this code:
async void connection()
{
var connString = "Host=Server1;Username=postgres;Password=pass;Database=BlazorData";
try
{
await using var conn = new NpgsqlConnection(connString);
await conn.OpenAsync();
errcheck = "success";
}
catch (Exception ex)
{
errcheck = ex.Message;
}
}
I explain how I use it with entity framework. It might help you.
in startup.cs, ConfigureServices method have this
services.AddEntityFrameworkNpgsql().AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));
You need two packages to be installed through nuget
Npgsql.EntityFrameworkCore.PostgreSQL
Npgsql.EntityFrameworkCore.PostgreSQL.Design
in appsetting.json make sure you have setup connection string correctly, below one is mine. Host can be localhost if database is in the same machine as the database
"DefaultConnection": "Host=192.168.16.240;Port=5432;Username=postgres;Password=mypassword;Database=mydatabase;"
That's basically it.
then define a application db context with your tables
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<Room> Rooms { get; set; }
public DbSet<Meal> Meals { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
in package mangaer console
add-migration initial
update-database
you should see the tables created in PgAdmin.
and use your dbsets like usual c# lists. and remember to inject applicationdbcontext in the controllers you need it.
The error says you need to resolve the hostname by yourself. Either pass an IP address or use Dns.GetHostEntry
using System.Linq;
using System.Net;
using System.Net.Sockets;
...
async void connection()
{
var host = Dns.GetHostEntry("Server1");
var firstIpV4Address = host.AddressList.First(a => a.AddressFamily == AddressFamily.InterNetwork);
var connString = $"Host={firstIpV4Address};Username=postgres;Password=pass;Database=BlazorData";
try
{
await using var conn = new NpgsqlConnection(connString);
await conn.OpenAsync();
errcheck = "success";
}
catch (Exception ex)
{
errcheck = ex.Message;
}
}

Sending SMS from BlackBerry Simulator

I'm developing a BlackBerry Application where I should send Text SMS from BlackBerry Device.
As I'm new to Blackberry, started few days back I'm unable to proceed.
Can anyone Help with providing code snippets for send SMS from BlackBerry Device or Simulator?
Thanks in Advance.
Suresh.
public static void sendSMS(final String no, final String msg) {
// try {
new Thread() {
public void run() {
boolean smsSuccess = false;
if (RadioInfo.getNetworkType() == RadioInfo.NETWORK_CDMA) {
DatagramConnection dc = null;
try {
dc = (DatagramConnection) Connector.open("sms://" + no);
byte[] data = msg.getBytes();
Datagram dg = dc.newDatagram(dc.getMaximumLength());
dg.setData(data, 0, data.length);
dc.send(dg);
// / send successfully
smsSuccess = true;
} catch (Exception e) {
System.out.println("Exception 1 : " + e.toString());
e.printStackTrace();
smsSuccess = false;
} finally {
try {
dc.close();
dc = null;
} catch (IOException e) {
System.out.println("Exception 2 : " + e.toString());
e.printStackTrace();
}
}
} else {
MessageConnection conn = null;
try {
conn = (MessageConnection) Connector
.open("sms://" + no);
TextMessage tmsg = (TextMessage) conn
.newMessage(MessageConnection.TEXT_MESSAGE);
tmsg.setAddress("sms://" + no);
tmsg.setPayloadText(msg);
conn.send(tmsg);
smsSuccess = true;
} catch (Exception e) {
smsSuccess = false;
System.out.println("Exception 3 : " + e.toString());
e.printStackTrace();
} finally {
try {
conn.close();
conn = null;
} catch (IOException e) {
System.out.println("Exception 4 : " + e.toString());
e.printStackTrace();
}
}
}
if(smsSuccess)
{
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// TODO Auto-generated method stub
Dialog.alert("success");
}
});
}else
{
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// TODO Auto-generated method stub
Dialog.alert("failure");
}
});
}
}
}.start();
}
Check out the the above code function .... to send SMS from Blackberry
You haven't specified what language you are developing in, but if you are developing in java and, if you are using Eclipse for your development with the Blackberry Java plugins, you will find a wealth of sample applications in the plugins folder hierarchy. The actual location will depend on where you have installed Eclipse, but e.g. on my machine they are at: C:\Program Files\Eclipse\eclipse 3.6.2 BlackBerry\plugins\net.rim.ejde.componentpack7.0.0_7.0.0.33\components\samples\com\rim\samples\device for the OS7 samples. Similar samples will exist for the different OS plugins you have installed.
There is a long standing sample in most OS sample sets called smsdemo which should give you all the code you need. Even if you are not developing in java, this sample should give you an indication of the path you need to take to fulfil your requirement.

WCF Data Services UpdateObject not working

I have a Silverlight client with a grid getting data from WCF Data Service. Works fine.
However if I want to update some changed grid row, the service data context UpdateObject is not working:
DataServiceContext.UpdateObject(MyGrid.SelectedItem);
foreach (Object item in DataServiceContext.Entities)
{
//
}
DataServiceContext.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, DataServiceContext);
I just have created a loop to inspect the values for the entities items and the value is not updated at all. BeginSaveChanges works fine, but it just uses not updated values.
Any ideas how to fix that?
thanks
Right a fully flushed out SaveChanges that will show the error message if EndSaveChanges() fails, like the code sample below. Obviously you can't use the console to write out your message in silverlight, but you get the idea.
For instance, when I wrote the following sample, I found that I was getting a forbidden error, because my entity set had EntitySetRights.AllRead, not EntitySetRights.All
class Program
{
private static AdventureWorksEntities svc;
static void Main(string[] args)
{
svc =
new AdventureWorksEntities(
new Uri("http://localhost:5068/AWDataService.svc",
UriKind.Absolute));
var productQuery = from p in svc.Products
where p.ProductID == 740
select p;
var product = productQuery.First();
ShowProduct(product);
product.Color = product.Color == "Silver" ? "Gray" : "Silver";
svc.UpdateObject(product);
svc.BeginSaveChanges(SaveChangesOptions.Batch, OnSave, svc);
ShowProduct(product);
Console.ReadKey();
}
private static void ShowProduct(Product product)
{
Console.WriteLine("Id: {0} Name: {1} Color: {2}",
product.ProductID, product.Name, product.Color);
}
private static void OnSave(IAsyncResult ar)
{
svc = ar.AsyncState as AdventureWorksEntities;
try
{
WriteResponse(svc.EndSaveChanges(ar));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void WriteResponse(DataServiceResponse response)
{
if(response.IsBatchResponse)
{
Console.WriteLine("Batch Response Code: {0}", response.BatchStatusCode);
}
foreach (ChangeOperationResponse change in response)
{
Console.WriteLine("Change code: {0}", change.StatusCode);
if(change.Error != null)
{
Console.WriteLine("\tError: {0}", change.Error.Message);
}
}
}
}

Resources