SignalR Javascript client can't connect, timeout occurs - signalr

I'm trying to connect to a signalR server with Javascript client. I can't get the JS client to connect to the server. My debug output shows that the client first tries to subscribe to Websocket, then SSE and makes Long Polling request, all of them get timeouts. The server is client to another signalR server and there is no problem with that connection. But the JS client cannot connect.
I have the below packages:
<package id="Microsoft.AspNet.SignalR" version="2.1.0" targetFramework="net451" />
<package id="Microsoft.AspNet.SignalR.Client" version="2.1.0" targetFramework="net451" />
<package id="Microsoft.AspNet.SignalR.Core" version="2.1.0" targetFramework="net451" />
<package id="Microsoft.AspNet.SignalR.JS" version="2.1.0" targetFramework="net451" />
<package id="Microsoft.AspNet.SignalR.Owin" version="1.2.1" targetFramework="net451" />
<package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.1.0" targetFramework="net451" />
My code is as below:
[assembly: OwinStartup(typeof(Startup))]
namespace CompanyPage
{
public class Startup
{
[ExceptionAspect]
public void Configuration(IAppBuilder app)
{
app.MapSignalR("/signalr", new HubConfiguration { EnableDetailedErrors = true });
}
}
}
.
protected void Session_Start(object sender, EventArgs e)
{
var context = GlobalHost.ConnectionManager.GetHubContext<ExchangeRate>();
context.Clients.All.insertOrder("TEST");
}
.
$(function () {
$.connection.hub.logging = true;
var chat = $.connection.exchangeRate;
chat.client.insertOrder = function(message) {
alert(message);
};
$.connection.hub.start().done(function() {
console.log("Connection Started");
});
});

Related

Connect NLog To Database Using Azure KeyVault Connection String In NetCore 3.1

My nlogconfig file is writing fine to a text file. It is also writing to a database when I include the connection string in appsettings.json. Now that we are ready to move to production, I am not going to be housing the connection string in appsettings.json.
However, the problem is that I do not know how to connect mynlogconfig file to a connection string that is located in Azure KeyVault.
How do I take this line of code in nlogconfig
connectionString="${configsetting:item=ConnectionStrings.DefaultConnection}"
and reference the connection string in Azure KeyVault?
My nlogconfig file:
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
<add assembly="NLog.Appsettings.Standard"/>
</extensions>
<targets>
<!-- local file target -->
<target name="fileTarget"
xsi:type="File"
fileName="C:\Nlog\logs\meLog.txt"
layout="
-------------- ${level} (${longdate}) --------------${newline}
${newline}
Call Site: ${callsite}${newline}
Exception Type: ${exception:format=Type}${newline}
Exception Message: ${exception:format=Message}${newline}
Stack Trace: ${exception:format=StackTrace}${newline}
Additional Info: ${message}${newline}" />
<target xsi:type="Database"
name="dbTarget"
connectionString="${configsetting:item=ConnectionStrings.DefaultConnection}"
commandText="INSERT INTO Logs(CreatedOn,Message,Level,Exception,StackTrace,Logger,Url) VALUES (#datetime,#msg,#level,#exception,#trace,#logger,#url)">
<parameter name="#datetime" layout="${date}" />
<parameter name="#msg" layout="${message}" />
<parameter name="#level" layout="${level}" />
<parameter name="#exception" layout="${exception:format=#}" />
<parameter name="#trace" layout="${stacktrace}" />
<parameter name="#logger" layout="${logger}" />
<parameter name="#url" layout="${aspnet-request-url}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Error" writeTo="dbTarget" />
<logger name="*" minlevel="Error" writeTo="fileTarget"/>
</rules>
</nlog>
My Program.cs file which is getting the database connection string from Azure KeyVault:
using Azure.Extensions.AspNetCore.Configuration.Secrets;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using WebApplication6.Models;
namespace WebApplication6
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
string MyClientID = "1MyClientID";
string MyTenantID = "1MyTenantID";
string MyClientSecretID = "1MyClientSecretID";
ClientSecretCredential credential =
new ClientSecretCredential(MyTenantID, MyClientID, MyClientSecretID);
var secretClient = new SecretClient(new Uri("https://somerandomurivault.vault.azure.net/"),
credential);
config.AddAzureKeyVault(secretClient, new KeyVaultSecretManager());
config.Build();
})
.ConfigureServices((hostContext, services)=>
{
var databaseConnectionString = hostContext.Configuration.GetValue<string>("databaseConnectionString");
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(databaseConnectionString);
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
I tried to set the connection string to a global variable, but I had no way of referencing this global variable in the nlogconfig file.

How to setup DI to inject ILogger<T> within a lambda function app with single lambda FunctionHandler

I have an MRE lambda project with csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<AWSProjectType>Lambda</AWSProjectType>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" Version="1.1.0" />
<PackageReference Include="Amazon.Lambda.Logging.AspNetCore" Version="3.0.1" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.6" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.6" />
</ItemGroup>
</Project>
And I have created a simple functionhandler which calls _svc.DoSomethingThatLogsUsingLogger();
as shown below
using Amazon.Lambda.Core;
using AWSLambda3.Services;
using Microsoft.Extensions.DependencyInjection;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace AWSLambda3
{
public class Function
{
private IServiceName1 _svc { get; }
public Function( IServiceName1 svc)
{
_svc = svc;
}
public Function()
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
serviceCollection.AddLogging();
var serviceProvider = serviceCollection.BuildServiceProvider();
_svc = serviceProvider.GetService<IServiceName1>();
}
private void ConfigureServices(IServiceCollection serviceCollection)
{
serviceCollection.AddTransient<IServiceName1, ServiceName1>();
}
public string FunctionHandler(string input, ILambdaContext context)
{
_svc.DoSomethingThatLogsUsingLogger();
return input?.ToString();
}
}
}
That service code simply attempts to log using ILogger
using Microsoft.Extensions.Logging;
using System;
namespace AWSLambda3.Services
{
public class ServiceName1 : IServiceName1
{
private readonly ILogger<ServiceName1> _logger;
public ServiceName1(ILogger<ServiceName1> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public void DoSomethingThatLogsUsingLogger()
{
_logger.LogTrace("test LogTrace log string");
_logger.LogDebug("test LogDebug log string");
_logger.LogInformation("test LogInformation log string");
_logger.LogWarning("test LogWarning log string");
_logger.LogError("test LogError log string");
_logger.LogCritical("test LogCritical log string");
}
}
}
However, upon deploying this lambda function handler to AWS Lambda, no logs are created in CloudWatch.
What am I missing?
Solution shown below in diff
Also need to ensure this package is installed
<PackageReference Include="Amazon.Lambda.Logging.AspNetCore" Version="3.0.1" />

asynchronous load ImagePart data error

I use DocumentFormat.OpenXml for generating docx. I try to load small png images (20-50 kb) to my docx asynchronously from WebClient. And I have different result for one code:
No problem
NullReferenceException
FileFormatException
ObjectDisposedException
InvalidOperationException
This code demonstrates my problem:
internal class Program
{
public static void Main(string[] args)
{
using (var outputStream = new MemoryStream())
{
using (var doc = WordprocessingDocument.Create(outputStream, WordprocessingDocumentType.Document))
{
var mainPart = doc.AddMainDocumentPart();
new Document(new Body()).Save(mainPart);
var tasks = Directory.GetFiles("images").Select(async it =>
await AddImagePart(it, mainPart.AddImagePart(ImagePartType.Png)).ConfigureAwait(false));
Task.WaitAll(tasks.ToArray());
}
File.WriteAllBytes("output.docx", outputStream.ToArray());
}
}
private static async Task AddImagePart(string path, ImagePart imagePart)
{
using (var client = new WebClient())
{
var image = await client.DownloadDataTaskAsync(path).ConfigureAwait(false);
imagePart.FeedData(new MemoryStream(image));
}
}
packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DocumentFormat.OpenXml" version="2.7.2" targetFramework="net46" />
<package id="System.IO.FileSystem.Primitives" version="4.0.1" targetFramework="net46" />
<package id="System.IO.Packaging" version="4.0.0" targetFramework="net46" />
</packages>
There are described on git problem with large files and .net less then 4.6. But I use small files and .net4.6.
Maybe you should read this post about async\await mistakes.
Try to make ConfigureAwait(false).

SignalR - How do I disable WebSockets

I upgraded to .NET 4.5, now SignalR seems insistent on using WebSockets in Firefox/Chrome - even though I'm only on Windows 7 which doesn't have a WebSocket Server.
The request obviously fails:
Firefox can't establish a connection to the server at ws://www.site.local/signalr?connectionData=
How do I force SignalR to forget about Websockets and use Long Polling, or is there a way of setting up Websockets for Windows 7 that I'm missing?
Update.... I'm using SignalR 0.4:
<package id="SignalR" version="0.4.0" />
<package id="SignalR.Hosting.AspNet" version="0.4.0.0" />
<package id="SignalR.Js" version="0.4.0.1" />
<package id="SignalR.Server" version="0.4.0.0" />
<package id="SignalR.StructureMap" version="0.4.1" />
I found the answer here:
https://github.com/SignalR/SignalR/wiki/SignalR-JS-Client
Basically:
$.connection.hubs.start({ transport: 'longPolling' }, function() {
console.log('connection started!');
});
In order to disable a transport on the server side, you must use something like this:
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Transports;
using Owin;
namespace MyApplication
{
public static class Startup
{
public static void ConfigureSignalR(IAppBuilder app)
{
// If using the global dependency resolver
TurnOfForeverFrame(GlobalHost.DependencyResolver);
app.MapSignalR();
}
public static void TurnOfForeverFrame(IDependencyResolver resolver)
{
var transportManager = resolver.Resolve<ITransportManager>() as TransportManager;
transportManager.Remove("foreverFrame");
}
}
}
The #reach4thelasers' solution only disable it in the client, but the client could re-enable the transport and connect.
Cheers.
For anyone looking how to disable it on the server using asp.net core 3.1:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub", options =>
{
options.Transports =
HttpTransportType.WebSockets |
HttpTransportType.LongPolling;
});
});
}
source: https://learn.microsoft.com/en-us/aspnet/core/signalr/configuration?view=aspnetcore-3.1&tabs=dotnet#advanced-http-configuration-options-1

Using log4net with ASP.NET to track Session variables

Our web app captures a user's login and stores it in a session variable, similar to Session("User_Id"). I'd like to use log4net to capture the User in the log.
I see a few references to using the MDC (Mapped Diagnostic Context) has been replaced with ThreadContext properties.
Has anyone implemented this ThreadContext approach? Any suggestions?
In the code...
log4net.ThreadContext.Properties["Log_User"] = userName;
in the web.config
<appender name="ADONetAppender" type="log4net.Appender.ADONetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="set in global.asax" />
<commandText value="INSERT INTO Log4Net ([Log_Date], [Severity],[Application],[Message], [Source], [Log_User]) VALUES (#log_date, #severity, #application, #message, #source, #currentUser)" />
<parameter>
<parameterName value="#log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
...
<parameter>
<parameterName value="#currentUser" />
<dbType value="String" />
<size value="100" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{Log_User}" />
</layout>
</parameter>
</appender>
I always encapsulate access to all Session variables in a class. This controls access and let's me use strong typing. I do any logging in this class. Here's an example:
public static class SessionInfo
{
private static readonly ILog log = LogManager.GetLogger(typeof(SessionInfo));
private const string AUDITOR_ID_KEY = "AuditorId";
static SessionInfo()
{
log.Info("SessionInfo created");
}
#region Generic methods to store and retrieve in session state
private static T GetSessionObject<T>(string key)
{
object obj = HttpContext.Current.Session[key];
if (obj == null)
{
return default(T);
}
return (T)obj;
}
private static void SetSessionObject<T>(string key, T value)
{
if (Equals(value, default(T)))
{
HttpContext.Current.Session.Remove(key);
}
{
HttpContext.Current.Session[key] = value;
}
}
#endregion
public static int AuditorId
{
get { return GetSessionObject<int>(AUDITOR_ID_KEY); }
set { SetSessionObject<int>(AUDITOR_ID_KEY, value); }
}
}

Resources