How to get parent AppDomain? - c#

I need to do something like this in c# (pseudo):
static var ns = new Non_Serializable_Nor_Marshal()
var app = new AppDomain();
app.execute(foo)
void foo()
{
var host = AppDomain.Current.Parent; //e.g. the original one
host.execute(bar)
}
void bar()
{
ns.Something();
}
IOW I have a non serializeable nor marshal object in one appdomain.
I want to create a second domain and execute foo(). From within that second domain I want to execute bar() on the original domain.
How do I pass the original domain to the child one?

If you don't want to use interop, you can also use a little trick using AppDomainManager. You can basically automatically 'wire' the 'primary' domain into any domains automatically - albiet the way I do it means you discard your real primary domain.
Here is the class that does all the magic:
/// <summary>
/// Represents a <see cref="AppDomainManager"/> that is
/// aware of the primary application AppDomain.
/// </summary>
public class PrimaryAppDomainManager : AppDomainManager
{
private static AppDomain _primaryDomain;
/// <summary>
/// Gets the primary domain.
/// </summary>
/// <value>The primary domain.</value>
public static AppDomain PrimaryDomain
{
get
{
return _primaryDomain;
}
}
/// <summary>
/// Sets the primary domain.
/// </summary>
/// <param name="primaryDomain">The primary domain.</param>
private void SetPrimaryDomain(AppDomain primaryDomain)
{
_primaryDomain = primaryDomain;
}
/// <summary>
/// Sets the primary domain to self.
/// </summary>
private void SetPrimaryDomainToSelf()
{
_primaryDomain = AppDomain.CurrentDomain;
}
/// <summary>
/// Determines whether this is the primary domain.
/// </summary>
/// <value>
/// <see langword="true"/> if this instance is the primary domain; otherwise, <see langword="false"/>.
/// </value>
public static bool IsPrimaryDomain
{
get
{
return _primaryDomain == AppDomain.CurrentDomain;
}
}
/// <summary>
/// Creates the initial domain.
/// </summary>
/// <param name="friendlyName">Name of the friendly.</param>
/// <param name="securityInfo">The security info.</param>
/// <param name="appDomainInfo">The AppDomain setup info.</param>
/// <returns></returns>
public static AppDomain CreateInitialDomain(string friendlyName, Evidence securityInfo, AppDomainSetup appDomainInfo)
{
if (AppDomain.CurrentDomain.DomainManager is PrimaryAppDomainManager)
return null;
appDomainInfo = appDomainInfo ?? new AppDomainSetup();
appDomainInfo.AppDomainManagerAssembly = typeof(PrimaryAppDomainManager).Assembly.FullName;
appDomainInfo.AppDomainManagerType = typeof(PrimaryAppDomainManager).FullName;
var appDomain = AppDomainManager.CreateDomainHelper(friendlyName, securityInfo, appDomainInfo);
((PrimaryAppDomainManager)appDomain.DomainManager).SetPrimaryDomainToSelf();
_primaryDomain = appDomain;
return appDomain;
}
/// <summary>
/// Returns a new or existing application domain.
/// </summary>
/// <param name="friendlyName">The friendly name of the domain.</param>
/// <param name="securityInfo">An object that contains evidence mapped through the security policy to establish a top-of-stack permission set.</param>
/// <param name="appDomainInfo">An object that contains application domain initialization information.</param>
/// <returns>A new or existing application domain.</returns>
/// <PermissionSet>
/// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="ControlEvidence, ControlAppDomain, Infrastructure"/>
/// </PermissionSet>
public override AppDomain CreateDomain(string friendlyName, Evidence securityInfo, AppDomainSetup appDomainInfo)
{
appDomainInfo = appDomainInfo ?? new AppDomainSetup();
appDomainInfo.AppDomainManagerAssembly = typeof(PrimaryAppDomainManager).Assembly.FullName;
appDomainInfo.AppDomainManagerType = typeof(PrimaryAppDomainManager).FullName;
var appDomain = base.CreateDomain(friendlyName, securityInfo, appDomainInfo);
((PrimaryAppDomainManager)appDomain.DomainManager).SetPrimaryDomain(_primaryDomain);
return appDomain;
}
}
And you need to alter your Main() (application entry) slightly:
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
new Program().Run(args);
}
void Run(string[] args)
{
var domain = PrimaryAppDomainManager.CreateInitialDomain("PrimaryDomain", null, null);
if (domain == null)
{
// Original Main() code here.
}
else
{
domain.CreateInstanceAndUnwrap<Program>().Run(args);
}
}
Now at any point you can get PrimaryAppDomainManager.PrimaryDomain to get a reference to the primary domain, just remember that it isn't the inital domain created by the .Net runtime - it's one we create immediately.
You can look at the comments in my blog post for an way to get the .Net runtime to hook this in for you automatically using the app.config.
Edit: I forgot to add the extension method I use, here it is:
/// <summary>
/// Creates a new instance of the specified type.
/// </summary>
/// <typeparam name="T">The type of object to create.</typeparam>
/// <param name="appDomain">The app domain.</param>
/// <returns>A proxy for the new object.</returns>
public static T CreateInstanceAndUnwrap<T>(this AppDomain appDomain)
{
var res = (T)appDomain.CreateInstanceAndUnwrap(typeof(T));
return res;
}

You could try referencing mscoree and then using its methods. I have used this in one of my projects.
mscoree will keep track of your AppDomains without any input.
/// <summary>
/// Returns the primary application domain.
/// </summary>
/// <returns>The primary application domain.</returns>
public static AppDomain GetPrimaryAppDomain()
{
return GetAppDomain(Process.GetCurrentProcess().MainModule.ModuleName);
}
/// <summary>
/// Returns the application domain with the given friendly name.
/// </summary>
/// <param name="friendlyName">The friendly name of the application domain.</param>
/// <returns>The application domain with the given friendly name.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if friendlyName is null.</exception>
public static AppDomain GetAppDomain(string friendlyName)
{
if (friendlyName == null)
{
throw new ArgumentNullException("friendlyName");
}
IntPtr handle = IntPtr.Zero;
CorRuntimeHostClass host = new CorRuntimeHostClass();
try
{
host.EnumDomains(out handle);
object domain = null;
while (true)
{
host.NextDomain(handle, out domain);
if (domain == null)
{
return null;
}
AppDomain appDomain = (AppDomain)domain;
if (appDomain.FriendlyName == friendlyName)
{
return appDomain;
}
}
}
finally
{
host.CloseEnum(handle);
Marshal.ReleaseComObject(host);
host = null;
}
}
(Adapted from http://www.dolittle.com/blogs/einar/archive/2007/05/18/cross-appdomain-singleton.aspx)

Related

FullSerializer & fsSerializer could not be found - Unity

I found some old Unity projects, but when I open them in Unity I get this errors:
The type or namespace name `FullSerializer' could not be found.
The type or namespace name `fsSerializer' could not be found.
This is the code:
using UnityEngine;
using UnityEngine.Assertions;
using FullSerializer;
namespace Game.Core
{
/// <summary>
/// Miscellaneous file utilities.
/// </summary>
public static class FileUtils
{
/// <summary>
/// Loads the specified json file.
/// </summary>
/// <param name="serializer">The FullSerializer serializer to use.</param>
/// <param name="path">The json file path.</param>
/// <typeparam name="T">The type of the data to load.</typeparam>
/// <returns>The loaded json data.</returns>
public static T LoadJsonFile<T>(fsSerializer serializer, string path) where T : class
{
var textAsset = Resources.Load<TextAsset>(path);
Assert.IsNotNull((textAsset));
var data = fsJsonParser.Parse(textAsset.text);
object deserialized = null;
serializer.TryDeserialize(data, typeof(T), ref deserialized).AssertSuccessWithoutWarnings();
return deserialized as T;
}
/// <summary>
/// Returns true if the specified path exists and false otherwise.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>True if the specified path exists; false otherwise.</returns>
public static bool FileExists(string path)
{
var textAsset = Resources.Load<TextAsset>(path);
return textAsset != null;
}
}
}

c# - Can I refactor functions that have similar inputs but call different services into one generic function?

I am looking for a way to combine x amount of very similar CRUD functions into one without having to use x amount of if else statements to check the type of a generic.
I have Web API controllers that I want to make calls from like this:
Service.Get<FooModel>(number, type, part, version);
This is to prevent having to have an extremely similar function for 40+ API endpoints. The issue is when I receive this in my service, I have to check the type of the generic given and compare with those 40+ object types in the one function. All of the models currently inherit from a base inherited model.
Current generic function
(Create, Update, Delete functions are similar):
public T Get<T>(string documentNr, string type, string part, string version) where T : InheritedModel, new()
{
try
{
T model = new T();
if (typeof(T) == typeof(InheritedModel))
{
using (var repo = new InheritedModelConsumer(ref _helper))
{
model = (T)repo.Get(documentNr, type, part, version);
}
}
else if (typeof(T) == typeof(FooModel))
{
using (var repo = new FooModelConsumer(ref _helper))
{
model = (T)(object)repo.Get(documentNr, type, part, version);
}
}
else if (typeof(T) == typeof(ComponentModel))
{
using (var repo = new ComponentModelConsumer(ref _helper))
{
model = (T)(object)repo.Get(documentNr, type, part, version);
}
}
else if (typeof(T) == typeof(BarModel))
{
using (var repo = new BarModelConsumer(ref _helper))
{
model = (T)(object)repo.Get(documentNr, type, part, version);
}
}
... and so on
... and so on
...
else
throw new Exception("Type T structure not defined");
return model;
}
catch (Exception)
{
throw;
}
finally
{
_helper.Dispose();
}
}
This does work, but if it is possible I am looking for something where I can say at run time, "oh I have this object of Type T, and well since I know the functions all have the same inputs I'm going to instantiate this consumer of Type TConsumer, call consumer.Get(inputs), and then return an object of T to whatever API controller called me."
Edit
Example of a simple consumer class in use
internal sealed class FooConsumer : RepositoryConsumer<Foo, FooRepository, FooFilter>
{
public FooConsumer(ref SqlHelper helper) : base(ref helper) { }
public List<Foo> GetAll(string token)
{
return _repo.Get().Where(x => Extensions.StringContainsToken(x.AccountName, token)).ToList();
}
}
Repository Consumer that all consumers inherit from .
T is the model, K is the Repository (custom ORM class), and O is Filter for the WHERE clause the ORM executes.
public abstract class RepositoryConsumer<T, K, O> : IDisposable, IRepositoryConsumer<T> where T : class, new() where K : Repository<T, O>, new() where O : QueryFilter, new()
{
/// <summary>
/// Repository instance
/// </summary>
protected K _repo;
/// <summary>
/// Only constructor avaialble. MUst pass SqlHelper instance for transaction support
/// </summary>
/// <param name="sql"></param>
public RepositoryConsumer(ref SqlHelper sql)
{
_repo = Activator.CreateInstance(typeof(K), new object[] { sql }) as K;
}
/// <summary>
/// Allow consumer initializations in using statements
/// </summary>
public void Dispose()
{
}
/// <summary>
/// Create instance of T
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public virtual int Create(T data)
{
return _repo.Create(data);
}
/// <summary>
/// Bulk create instances of T
/// </summary>
/// <param name="contract"></param>
/// <returns></returns>
public virtual int Create(BaseBulkable<T> contract)
{
return _repo.BulkCreate(contract);
}
/// <summary>
/// Get an instance of T based on a single PK field id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual T Get(long id)
{
return _repo.Get(id);
}
/// <summary>
/// Gets all instances of T
/// </summary>
/// <returns></returns>
public virtual List<T> GetAll()
{
return _repo.Get();
}
/// <summary>
/// Updates an instance of T
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public virtual int Update(T data)
{
return _repo.Update(data);
}
/// <summary>
/// Updates an instance of T based on a single PK field id
/// </summary>
/// <param name="id"></param>
/// <param name="data"></param>
/// <returns></returns>
public virtual int Update(long id, T data)
{
return _repo.Update(id, data);
}
/// <summary>
/// Deletes an instance of T
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public virtual int Delete(T data)
{
return _repo.Delete(data);
}
/// <summary>
/// Deletes an instance of T based on a single PK field id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual int Delete(long id)
{
return _repo.Delete(id);
}
}

Hyper-V Cluster - Shared Disk replication througth WMI

First of all, I wanna say thanks to this awesome site, saved my life more than a hundred times.
To introduce a little the problem we're having, I'll begin explaining our infrastructure.
Actually, we've got a client that has 4 Hyper-V host(s) using Failover Cluster feature, with Windows 2016.
Microsoft says in releases notes that shared disk replication is only available througth the WMI class Msvm_ReplicationCollectionService, so said, we started working on it.
-- Msvm_CollectionReplicationService Class
https://msdn.microsoft.com/en-us/library/mt167787(v=vs.85).aspx
We've implemented the class following the old model of this same class.
Old namespace: "root/virtualization/v2"
(this works well, but no shared disk replication)
New namespace: "root/HyperVCluster/v2"
(fails)
As first step we try to create a relationship between the two virtual machines sharing the disk, using previous created collection (ReplicaTestGroup), then we try to call "CreateReplicationRelationship" method of the class.
Issued command: PS C:\REPLICA\1\1> .\ReplicaSamples.exe CreateReplicationRelationship REPLICA1 REPLICA2 7ccff3fe-da17-436a-8f38-8a34833b31e6 hypervdrhost.mydom.local
Method fails with: "The method call failed.", without more details.
Does anyone has any idea of what's going on? Is there any way of debugging WMI so I can see what's wrong?
ERROR:
Unhandled Exception: System.Management.ManagementException: The method
call failed. at
Microsoft.Samples.HyperV.Common.WmiUtilities.ValidateOutput(ManagementBaseObject
outputParameters, ManagementScope scope, Boolean throwIfFailed,
Boolean printErrors) in
C:\Users\isarria\Documents\Replica\cs\WmiUtilities.cs:line 136 at
Microsoft.Samples.HyperV.Common.WmiUtilities.ValidateOutput(ManagementBaseObject
outputParameters, ManagementScope scope) in
C:\Users\isarria\Documents\Replica\cs\WmiUtilities.cs:line 59 at
Microsoft.Samples.HyperV.Replica.ManageReplication.CreateReplicationRelationship(String
name, String name2, String CollectionID, String recoveryServerName) in
C:\Users\isarria\Documents\Replica\cs\ManageReplication.cs:line 85 at
Microsoft.Samples.HyperV.Replica.Program.Main(String[] args) in
C:\Users\isarria\Documents\Replica\cs\Program.cs:line 107
USED CODE:
/// <summary>
/// Enables replication for a collection of virtual machines to a specified DRserver using
/// integrated authentication.
/// </summary>
/// <param name="name">Name of VM 1</param>
/// <param name="name2">Name of VM 2</param>
/// <param name="CollectionID">CollectionID to enable replication.</param>
/// <param name="recoveryServerName">The name of the recovery server.</param>
internal static void
CreateReplicationRelationship(
string name,
string name2,
string CollectionID,
string recoveryServerName)
{
ManagementScope scope = new ManagementScope(#"root\HyperVCluster\v2");
ManagementScope oldScope = new ManagementScope(#"root\virtualization\v2");
//
// Retrieve the Msvm_VirtualSystemCollection.
//
using (ManagementObject vm = WmiUtilities.GetVirtualMachine(name, oldScope))
{
using (ManagementObject vm2 = WmiUtilities.GetVirtualMachine(name2, oldScope))
{
string vmPath = vm.Path.Path;
string vmPath2 = vm2.Path.Path;
using (ManagementObject collection = WmiUtilities.GetVMGroup(CollectionID, scope))
{
using (ManagementObject replicationSettingData =
ReplicaUtilities.GetReplicationSettings(vm))
{
replicationSettingData["RecoveryConnectionPoint"] = recoveryServerName;
replicationSettingData["AuthenticationType"] = 1;
replicationSettingData["RecoveryServerPortNumber"] = 80;
replicationSettingData["CompressionEnabled"] = 1;
// Keep 24 recovery points.
replicationSettingData["RecoveryHistory"] = 24;
// Replicate changes after every 300 seconds.
replicationSettingData["ReplicationInterval"] = 300;
// Take VSS snapshot every one hour.
replicationSettingData["ApplicationConsistentSnapshotInterval"] = 1;
// Include all disks for replication.
replicationSettingData["IncludedDisks"] = WmiUtilities.GetVhdSettings(vm);
//replicationSettingData["IncludedDisks"] = WmiUtilities.GetVhdSettings(vm2);
Console.WriteLine(replicationSettingData["IncludedDisks"].ToString());
string settingDataEmbedded =
replicationSettingData.GetText(TextFormat.WmiDtd20);
using (ManagementObject replicationService =
ReplicaUtilities.GetVirtualMachineReplicationService(scope))
{
using (ManagementBaseObject inParams =
replicationService.GetMethodParameters("CreateReplicationRelationship"))
{
inParams["Collection"] = collection;
inParams["CollectionReplicationSettingData"] = settingDataEmbedded;
using (ManagementBaseObject outParams =
replicationService.InvokeMethod("CreateReplicationRelationship",
inParams,
null))
{
WmiUtilities.ValidateOutput(outParams, scope);
}
}
}
Console.WriteLine(string.Format(CultureInfo.CurrentCulture,
"Replication is successfully enabled for vmGroup: \"{0}\"", CollectionID));
}
}
}
}
}
/// <summary>
/// Gets the Msvm_VirtualSystemCollection instance that matches the requested VMGroup name.
/// </summary>
/// <param name="CollectionID">The CollectionID to retrieve the path for.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The Msvm_VirtualSystemCollection instance.</returns>
public static ManagementObject
GetVMGroup(
string CollectionID,
ManagementScope scope)
{
return GetCollectionObject(CollectionID, "Msvm_VirtualSystemCollection", scope);
}
/// <summary>
/// Gets the Msvm_ComputerSystem instance that matches the requested virtual machine name.
/// </summary>
/// <param name="name">The name of the virtual machine to retrieve the path for.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The Msvm_ComputerSystem instance.</returns>
public static ManagementObject
GetVirtualMachine(
string name,
ManagementScope scope)
{
return GetVmObject(name, "Msvm_ComputerSystem", scope);
}
/// <summary>
/// Gets the first virtual machine object of the given class with the given name.
/// </summary>
/// <param name="name">The name of the virtual machine to retrieve the path for.</param>
/// <param name="className">The class of virtual machine to search for.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The instance representing the virtual machine.</returns>
private static ManagementObject
GetVmObject(
string name,
string className,
ManagementScope scope)
{
string vmQueryWql = string.Format(CultureInfo.InvariantCulture,
"SELECT * FROM {0} WHERE ElementName=\"{1}\"", className, name);
SelectQuery vmQuery = new SelectQuery(vmQueryWql);
using (ManagementObjectSearcher vmSearcher = new ManagementObjectSearcher(scope, vmQuery))
using (ManagementObjectCollection vmCollection = vmSearcher.Get())
{
if (vmCollection.Count == 0)
{
throw new ManagementException(string.Format(CultureInfo.CurrentCulture,
"No {0} could be found with name \"{1}\"",
className,
name));
}
//
// If multiple virtual machines exist with the requested name, return the first
// one.
//
ManagementObject vm = GetFirstObjectFromCollection(vmCollection);
return vm;
}
}
/// <summary>
/// Gets the replication settings object for a collection.
/// </summary>
/// <param name="systemCollection">The Msvm_VirtualSystemCollection mache object.</param>
/// <returns>The replication settings object.</returns>
internal static ManagementObject
GetReplicationSettings(
ManagementObject systemCollection)
{
using (ManagementObjectCollection settingsCollection =
systemCollection.GetRelated("Msvm_ReplicationSettingData"))
{
ManagementObject replicationSettings =
WmiUtilities.GetFirstObjectFromCollection(settingsCollection);
return replicationSettings;
}
}
/// <summary>
/// Gets the first virtual machine object of the given class with the given name.
/// </summary>
/// <param CollectionID="CollectionID">The name of the virtual machine to retrieve the path for.</param>
/// <param name="className">The class of virtual machine to search for.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns>The instance representing the virtual machine.</returns>
private static ManagementObject
GetCollectionObject(
string CollectionID,
string className,
ManagementScope scope)
{
string vmQueryWql = string.Format(CultureInfo.InvariantCulture,
"SELECT * FROM {0} WHERE CollectionID=\"{1}\"", className, CollectionID);
SelectQuery vmQuery = new SelectQuery(vmQueryWql);
using (ManagementObjectSearcher vmSearcher = new ManagementObjectSearcher(scope, vmQuery))
using (ManagementObjectCollection vmCollection = vmSearcher.Get())
{
ManagementObject CollectionObject = null;
if (vmCollection.Count == 1)
{
foreach (ManagementObject managementObject in vmCollection)
{
CollectionObject = managementObject;
}
}
else
{
throw new ManagementException(string.Format(CultureInfo.CurrentCulture,
"No {0} could be found with ID \"{1}\"",
className,
CollectionID));
}
return CollectionObject;
}
}
/// <summary>
/// Gets the virtual system replication service.
/// </summary>
/// <param name="scope">The scope to use when connecting to WMI.</param>
/// <returns>The collection virtual machine replication service.</returns>
public static ManagementObject
GetVirtualMachineReplicationService(
ManagementScope scope)
{
ManagementScope scope2 = new ManagementScope(#"root\HyperVCluster\v2");
SelectQuery query = new SelectQuery("select * from Msvm_CollectionReplicationService");
using (ManagementObjectSearcher queryExecute = new ManagementObjectSearcher(scope2, query))
using (ManagementObjectCollection serviceCollection = queryExecute.Get())
{
if (serviceCollection.Count == 0)
{
throw new ManagementException("Cannot find the collection replication service object. " +
"Please check that the Hyper-V Virtual Machine Management service is running.");
}
return WmiUtilities.GetFirstObjectFromCollection(serviceCollection);
}
}
Also, here is ValidateOutput method.
/// <summary>
/// Validates the output parameters of a method call and prints errors, if any.
/// </summary>
/// <param name="outputParameters">The output parameters of a WMI method call.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <returns><c>true</c> if successful and not firing an alert; otherwise, <c>false</c>.</returns>
public static bool
ValidateOutput(
ManagementBaseObject outputParameters,
ManagementScope scope)
{
return ValidateOutput(outputParameters, scope, true, false);
}
/// <summary>
/// Validates the output parameters of a method call and prints errors, if any.
/// </summary>
/// <param name="outputParameters">The output parameters of a WMI method call.</param>
/// <param name="scope">The ManagementScope to use to connect to WMI.</param>
/// <param name="throwIfFailed"> If true, the method throws on failure.</param>
/// <param name="printErrors">If true, Msvm_Error messages are displayed.</param>
/// <returns><c>true</c> if successful and not firing an alert; otherwise, <c>false</c>.</returns>
public static bool
ValidateOutput(
ManagementBaseObject outputParameters,
ManagementScope scope,
bool throwIfFailed,
bool printErrors)
{
bool succeeded = true;
string errorMessage = "The method call failed.";
if ((uint)outputParameters["ReturnValue"] == 4096)
{
//
// The method invoked an asynchronous operation. Get the Job object
// and wait for it to complete. Then we can check its result.
//
using (ManagementObject job = new ManagementObject((string)outputParameters["Job"]))
{
job.Scope = scope;
while (!IsJobComplete(job["JobState"]))
{
Thread.Sleep(TimeSpan.FromSeconds(1));
//
// ManagementObjects are offline objects. Call Get() on the object to have its
// current property state.
//
job.Get();
}
if (!IsJobSuccessful(job["JobState"]))
{
succeeded = false;
//
// In some cases the Job object can contain helpful information about
// why the method call failed. If it did contain such information,
// use it instead of a generic message.
//
if (!string.IsNullOrEmpty((string)job["ErrorDescription"]))
{
errorMessage = (string)job["ErrorDescription"];
}
if (printErrors)
{
PrintMsvmErrors(job);
}
if (throwIfFailed)
{
throw new ManagementException(errorMessage);
}
}
}
}
else if ((uint)outputParameters["ReturnValue"] != 0)
{
succeeded = false;
if (throwIfFailed)
{
throw new ManagementException(errorMessage);
}
}
return succeeded;
}

.net core websockets obtain DbContext

I am testing out .net core and making a small sample app using .net core + websockets to push some data into my app. I want to save this data in the database using a dbcontext.
However I have issues getting the dbcontext in my websocket handler. So how can I create a dbcontext to use.
My startup Configure method contains this:
...
app.Map("/ws", WSHandler.Map);
...
This is my WSHandler class that implements actually reading from the incoming connection. I need a DbContext here that I can use to read/write from the database.
/// <summary>
/// Handler for an incoming websocket client
/// </summary>
public class WSHandler {
/// <summary>
/// Max size in bytes of an incoming/outgoing message
/// </summary>
public const int BufferSize = 4096;
/// <summary>
/// The socket of the current connection
/// </summary>
WebSocket socket;
/// <summary>
/// Constructor, assign socket to current instance and adds socket to ConnectedClients.
/// </summary>
/// <param name="socket"></param>
WSHandler(WebSocket socket) {
this.socket = socket;
}
/// <summary>
/// Configure app to use websockets and register handler.
/// </summary>
/// <param name="app"></param>
public static void Map(IApplicationBuilder app) {
app.UseWebSockets();
app.Use((WSHandler.Acceptor);
}
/// <summary>
/// Accept HttpContext and handles constructs instance of WSHandler.
/// </summary>
/// <param name="hc">The HttpContext</param>
/// <param name="n">Task n</param>
/// <returns></returns>
static async Task Acceptor(HttpContext hc, Func<Task> n) {
if (hc.WebSockets.IsWebSocketRequest == false) {
return;
}
var socket = await hc.WebSockets.AcceptWebSocketAsync();
var h = new WSHandler(socket);
await h.Loop();
}
/// <summary>
/// Wait's for incoming messages
/// </summary>
/// <returns></returns>
async Task Loop() {
var buffer = new Byte[BufferSize];
ArraySegment<Byte> segment = new ArraySegment<byte>(buffer);
while (this.socket.State == WebSocketState.Open) {
WebSocketReceiveResult result = null;
do {
result = await socket.ReceiveAsync(segment, CancellationToken.None);
} while (result.EndOfMessage == false);
// do something with message here. I want to save parse and save to database
}
}
}
Since there is some interests in this post I have added the solution I used.
You have access to all services via the HttpContext. So what I did is get the context options from this service and then create context when I need them. Be aware though that long living contexts are not advised and if an error occurs a DbContext is no longer useable. In the end I implemented a different database caching layer and write to that instead of using DbContext itself in the websocket handler.
Here is the code above extended to create DbContexts. I have not tested it since right now I don't have visual studio available...
<summary>
/// Handler for an incoming websocket client
/// </summary>
public class WSHandler {
/// <summary>
/// Max size in bytes of an incoming/outgoing message
/// </summary>
public const int BufferSize = 4096;
/// <summary>
/// The socket of the current connection
/// </summary>
WebSocket socket;
/// <summary>
/// The options to create DbContexts with.
/// </summary>
DbContextOptions<AssemblyServerContext> ctxOpts;
/// <summary>
/// Constructor, assign socket to current instance and adds socket to ConnectedClients.
/// </summary>
/// <param name="socket"></param>
/// <param name="ctxOpts"></param>
WSHandler(WebSocket socket, DbContextOptions<AssemblyServerContext> ctxOpts) {
this.ctxOpts = ctxOpts;
this.socket = socket;
}
/// <summary>
/// Configure app to use websockets and register handler.
/// </summary>
/// <param name="app"></param>
public static void Map(IApplicationBuilder app) {
app.UseWebSockets();
app.Use((WSHandler.Acceptor);
}
/// <summary>
/// Accept HttpContext and handles constructs instance of WSHandler.
/// </summary>
/// <param name="hc">The HttpContext</param>
/// <param name="n">Task n</param>
/// <returns></returns>
static async Task Acceptor(HttpContext hc, Func<Task> n) {
if (hc.WebSockets.IsWebSocketRequest == false) {
return;
}
var socket = await hc.WebSockets.AcceptWebSocketAsync();
var ctxOptions = hc.RequestServices.GetService<DbContextOptions<AssemblyServerContext>>();
var h = new WSHandler(socket, ctxOptions);
await h.Loop();
}
/// <summary>
/// Wait's for incoming messages
/// </summary>
/// <returns></returns>
async Task Loop() {
var buffer = new Byte[BufferSize];
ArraySegment<Byte> segment = new ArraySegment<byte>(buffer);
while (this.socket.State == WebSocketState.Open) {
WebSocketReceiveResult result = null;
do {
result = await socket.ReceiveAsync(segment, CancellationToken.None);
} while (result.EndOfMessage == false);
// do something with message here. I want to save parse and save to database
using (var ctx = new AssemblyServerContext(ctxOpts)) {
}
}
}
}

access Session variable from aspx into UserControl

I have a Session["Name"] in my aspx.cs file
how to access it from the UserControl codebehind on the same page
Thanks,
try like this:
string name= HttpContext.Current.Session["Name"].ToString();
or
string name=Session["Name"].ToString();
You need to create an object from that control.
Without see a little bit of the code, it would be hard to tell.
Maybe the session is timing out
Is there an error happing that causes the session state to be clear, or an logout
Modifying the web.config or many files can cause the application to restart.
Finally I have to ask:
- Is session disabled in some way? Does it work between other pages? Maybe it is disabled for Ajax requests?
- Is is maybe a magic string error.
Personally, to avoid magic string errors, I use a Session Wrapper:
/// <summary>
/// The session manager
/// </summary>
public sealed class SessionManager
{
#region ISessionManager Members
/// <summary>
/// Clears the session.
/// </summary>
public void ClearSession()
{
HttpContext.Current.Session.Clear();
HttpContext.Current.Session.Abandon(); //Abandon ends the entire session (the user gets a new SessionId)
}
/// <summary>
/// Gets or sets the current employe.
/// </summary>
/// <value>The current employe.</value>
public EmployeDto CurrentEmploye
{
get { return Get<EmployeDto>(); }
set { Add(value); }
}
/// <summary>
/// Gets or sets the parameters.
/// </summary>
/// <value>The parameters.</value>
public IList<ParameterDto> Parameters
{
get { return Get<List<ParameterDto>>() ?? new List<ParameterDto>(); }
set { Add(value); }
}
#endregion
#region Methods
/// <summary>
/// Adds the specified key.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <param name="key">The key.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
/// <exception cref="System.ArgumentNullException">key</exception>
/// <exception cref="System.Exception">Session elements cannot be added when session is disabled.</exception>
public static bool Add<T>(T value, [CallerMemberName] string key = null)
{
if (key == null) throw new ArgumentNullException("key");
HttpContext current = HttpContext.Current;
if (current == null)
{
return false;
}
if (current.Session.Mode == SessionStateMode.Off)
{
throw new Exception("Session elements cannot be added when session is disabled.");
}
current.Session.Add(key, value);
return true;
}
/// <summary>
/// Gets the specified key.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key">The key.</param>
/// <returns>``0.</returns>
/// <exception cref="System.ArgumentNullException">key</exception>
/// <exception cref="System.Exception">Session elements cannot be added when session is disabled.</exception>
public static T Get<T>([CallerMemberName] string key = null) where T : class
{
if (key == null) throw new ArgumentNullException("key");
HttpContext current = HttpContext.Current;
if (current.Session.Mode == SessionStateMode.Off)
{
throw new Exception("Session elements cannot be added when session is disabled.");
}
return current.Session[key] as T;
}
/// <summary>
/// Gets the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
/// <exception cref="System.ArgumentNullException">key</exception>
/// <exception cref="System.Exception">Session elements cannot be added when session is disabled.</exception>
public static bool Get([CallerMemberName] string key = null)
{
if (key == null) throw new ArgumentNullException("key");
HttpContext current = HttpContext.Current;
if (current.Session.Mode == SessionStateMode.Off)
{
throw new Exception("Session elements cannot be added when session is disabled.");
}
bool result = false;
bool.TryParse(current.Session[key].ToString(), out result);
return result;
}
/// <summary>
/// Removes the specified key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
/// <exception cref="System.ArgumentNullException">key</exception>
/// <exception cref="System.Exception">Session elements cannot be added when session is disabled.</exception>
public static bool Remove(string key)
{
if (key == null) throw new ArgumentNullException("key");
HttpContext current = HttpContext.Current;
if (current == null)
{
return false;
}
if (current.Session.Mode == SessionStateMode.Off)
{
throw new Exception("Session elements cannot be added when session is disabled.");
}
current.Session.Remove(key);
return true;
}
#endregion
}
My example uses reflection to define the key name as the same as the property name, but you can use constants instead. It also checks if the Session is disabled, which might help in debugging your case.
Try this as well:
HttpContext.Current.Session["Name"]

Categories

Resources