Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
itskage
Aug 26, 2003


Oh duh. Sorry, I even asked another senior dev. Hectic week with another phase of implementation on this project going down.

Adbot
ADBOT LOVES YOU

Banjo Bones
Mar 28, 2003

Sorry, I think this was the wrong thread to ask this in... moved to the Excel thread.

Banjo Bones fucked around with this message at 22:48 on Jun 11, 2017

Destroyenator
Dec 27, 2004

Don't ask me lady, I live in beer

Munkeymon posted:

ASP still won't route something that looks like a number to {*url} though. I hate the way ASP does routing :argh:

e: Really anything in .Net that's run-it-and-see-if-it-works is maddening because that's what a compiler is supposed to be for
If you can deal with the fiddly setup, using the ASP TestServer stuff can be really nice for sorting out these issues. For pre-core stuff you have to set the project up as an OWIN thing (slightly different configure signature but it still runs on IIS) and it can take a little while to get all the right packages in place but it essentially creates an in-memory server and gives you an HttpClient pointing at it. You call into the Configure step so set up whatever mocks for DI and then you get fast, isolated, tests of your app including routing, deserialisation and filters.

I haven't bothered with the setup on many projects but I think it's worthwhile spending the time on big enough ones. We've caught some tricky deserialisation problems with it and it's great to have instant turnaround on route conflicts etc.

mortarr
Apr 28, 2005

frozen meat at high speed
Has anyone done any work with the azure app proxy and azure active directory? I'm hosting a site internal to my domain which is also available via the azure app proxy, and I can't figure out how to change a user (eg log out/log back in).

I think part of my issue is that because I'm using the app proxy / azure ad, I don't have any authentication stuff in my app other than the usual security tags for windows auth in web.config, so can't use any of the owin(?) authentication calls server-side. Another problem is that a lot of the azure/asp.net examples seem to target azure as-it-was and not as it is today.

Just wanted to rant, I guess, this poo poo is really loving frustrating.

Mr.Misfit
Jan 10, 2013

The time for
SkellyBones
has come!
A quick question, if I may. I´ve set-up a node.JS server with self-signed certificates via TinyCA and now want to connect to it from a self-written app via httpwebrequest written in Visual Basic and I´m constantly getting "application didn´t make itself trustworthy on ssl/tsl-channel" despite sending the .pem certificate the server has also included as an x509certificate alongside the webrequest. Anyone here know what I´m doing wrong?

The code I´m using for the request:
code:
    Function connect()
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
        Dim localhost As New Uri("https://127.0.0.1:8081") 
        Dim cert As X509Certificate = X509Certificate.CreateFromCertFile(".\cert.pem")
        Dim request As HttpWebRequest = WebRequest.Create(localhost)
        request.ClientCertificates.Add(cert)
        Dim response As WebResponse = request.GetResponse()
        Dim dataStream As Stream = response.GetResponseStream()
        Dim reader As New StreamReader(dataStream)
        Dim responseFromServer As String = reader.ReadToEnd()
        Dim ergebnis = jSONConvert(responseFromServer)
        reader.Close()
        response.Close()
        Return ergebnis
    End Function

Mr.Misfit fucked around with this message at 02:10 on Jun 15, 2017

B-Nasty
May 25, 2005

I don't understand why you're sending a cert from the client unless you're using mutual SSL. If you can hit this endpoint from, say CURL, then you just need to trust the server's cert. You can quickly test if this is the problem by trusting all certs on the client. I think the VB syntax is something like

System.Net.ServicePointManager.ServerCertificateValidationCallback = (Function(sender, certificate, chain, sslPolicyErrors) True)

You need to install the server's cert into your certificate store in order to trust it.

Mr.Misfit
Jan 10, 2013

The time for
SkellyBones
has come!
It seems I might have a misunderstanding on my hand.
I´m sending the certificate to try and validate the web request. I take it from your words that isn´t necessary?

Edit: Interesting. Starting the WebRequest with the line you advised above actually "freezes" the app but the connection is suddenly validated, even if it´s still denied by the web server. Now to find out why my node.JS server denies the access and freezes the app then.

Edit2: It actually leads to a Timeout for the app.

Mr.Misfit fucked around with this message at 01:21 on Jun 15, 2017

B-Nasty
May 25, 2005

Mr.Misfit posted:

It seems I might have a misunderstanding on my hand.
I´m sending the certificate to try and validate the web request. I take it from your words that isn´t necessary?

Probably (99% likely) not. Mutual SSL is pretty rarely used, and you'd know it if you were using it.

Take the cert that you're using on the server, and walk through this guide: https://blogs.technet.microsoft.com/sbs/2008/05/08/installing-a-self-signed-certificate-as-a-trusted-root-ca-in-windows-vista/ from step 4. (double click on cert)

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Mr.Misfit posted:

A quick question, if I may. I´ve set-up a node.JS server with self-signed certificates via TinyCA and now want to connect to it from a self-written app via httpwebrequest written in Visual Basic and I´m constantly getting "application didn´t make itself trustworthy on ssl/tsl-channel" despite sending the .pem certificate the server has also included as an x509certificate alongside the webrequest. Anyone here know what I´m doing wrong?

The code I´m using for the request:
code:
    Function connect()
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
        Dim localhost As New Uri("https://127.0.0.1:8081") 
        Dim cert As X509Certificate = X509Certificate.CreateFromCertFile(".\cert.pem")
        Dim request As HttpWebRequest = WebRequest.Create(localhost)
        request.ClientCertificates.Add(cert)
        Dim response As WebResponse = request.GetResponse()
        Dim dataStream As Stream = response.GetResponseStream()
        Dim reader As New StreamReader(dataStream)
        Dim responseFromServer As String = reader.ReadToEnd()
        Dim ergebnis = jSONConvert(responseFromServer)
        reader.Close()
        response.Close()
        Return ergebnis
    End Function

One thing you're doing wrong is using spoiler tags instead of code tags.

Mr.Misfit
Jan 10, 2013

The time for
SkellyBones
has come!

B-Nasty posted:

Probably (99% likely) not. Mutual SSL is pretty rarely used, and you'd know it if you were using it.

Take the cert that you're using on the server, and walk through this guide: https://blogs.technet.microsoft.com/sbs/2008/05/08/installing-a-self-signed-certificate-as-a-trusted-root-ca-in-windows-vista/ from step 4. (double click on cert)

Okay, so I´m trying to import the certificate into the certificate store. Only to find, that apprently the format I exported with TinyCA was wrong, so I´m exporting it again in the recognised format...and find that I´ve misplaced the certificate password...grmpfl.

New Yorp New Yorp posted:

One thing you're doing wrong is using spoiler tags instead of code tags.

Fixed that. Thank you for telling me =)

Mr.Misfit
Jan 10, 2013

The time for
SkellyBones
has come!
Edit: Da...f....sorry for the doublepost?

EssOEss
Oct 23, 2006
128-bit approved
A certificate is a document from a trusted party (the Certificate Authority) saying "Person/website/company/domainname X controls private key Y". Web servers present certificates to browsers/clients to prove who they represent (mostly to prove that they are a server legitimately authorized to serve https://www.yourbank.com though it can also identify the company and non-digital-world entities) together with a mathematical proof that they control private key Y (without revealing it) to show that the document talks about them.

When a client connects to a server, it looks at this certificate and now needs to make a decision: do I trust what it says? After all, anyone can say "I am authorized to serve https://www.yourbank.com please send me all your money". To enable this decision to be made, each certificate is digitally signed by the CA and each client has a list of CAs that it trusts.

So, the client will check "Is the CA who signed it in my list of trusted CAs?" and block the connection if not.

If you use a self-signed certificate then the CA itself is the same entity being certified (it signs its own certificate). So this certificate needs to be in the trusted CAs certificate store used by the client system. This will not be the case by default.

On Windows, you can access the current user's certificate store manager via certmgr.msc and the machine-level one via manually adding the relevant Certificates snap-in in mmc. Please just add your development certificates to the trusted CAs store and don't just disable TLS verification in your app, which you will then end up forgetting about and will thereby forever publish unsecure apps.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
I'm trying to be crazy with generics again.

I have a serialization framework for a personal Unity game project. I'm looking for implementations of the given generic factory interface:

(note that I stripped some descriptive text to flatten all this)
code:
public interface ISaveLoadFactory<TEntity, TComponent>
{
    object CreateSaveHandle(TComponent component);
    void LoadFromSerializer(object serializedHandle, TEntity parent, Dictionary<SceneObjectId, TEntity> objectMap);
    string GetSerializerName();
    Type GetRecordType();
    Type GetComponentType();
    List<TEntity> GetStrongReferencedEntities(TComponent component);

}
I made it generic because I've moved the code out of Unity into a separate library and I have a mock testbench for testing my internal logic is working. It turns out that most implementations of this interface do some pretty typical things, and I could nail it with a generic like this:

code:
public abstract class BasicSaveLoadFactory<TRecord, TEntity, TComponent> : ISaveLoadFactory<TEntity, TComponent>
{
    public object CreateSaveHandle(TComponent component)
    {
        return Save(component);
    }

    public Type GetComponentType()
    {
        return typeof(TComponent);
    }

    public Type GetRecordType()
    {
        return typeof(TRecord);
    }

    public string GetSerializerName()
    {
        return typeof(TComponent).ToString();
    }

    public List<TEntity> GetStrongReferencedEntities(TComponent component)
    {
        // Override if you actually need to implement this!
        return null;
    }

    public void LoadFromSerializer(object serializedHandle, TEntity parent, Dictionary<SceneObjectId, TEntity> objectMap)
    {
        var converted = (TRecord)serializedHandle;
        Load(converted, parent, objectMap);
    }

    public abstract void Load(TRecord record, TEntity parent, Dictionary<SceneObjectId, TEntity> objectMap);
    public abstract TRecord Save(TComponent component);
}
This collapses it down to a basic save/load call. In the LoadFromSerializer call. I thought all was good in the world, but my code to scan for factories won't pick up BasicSaveLoadFactory classes:

code:
    public static Dictionary<Type, ISaveLoadFactory<TEntity, TComponent>> GetFactoryMap()
    {

        // Regular factory lookup table
        var factoryLookup = new Dictionary<Type, ISaveLoadFactory<TEntity, TComponent>>();
        var rawFactoryTypes = System.AppDomain.CurrentDomain.GetAllDerivedTypes(typeof(ISaveLoadFactory<TEntity, TComponent>));
        foreach (var factoryType in rawFactoryTypes)
        {
            var instance = (ISaveLoadFactory<TEntity, TComponent>)Activator.CreateInstance(factoryType);
            factoryLookup.Add(instance.GetComponentType(), instance);
        }

        return factoryLookup;
    }
I tried also scanning for BasicSaveLoadFactory but I can't pick up anything. The big problem there is that I don't have TRecord and just stubbing in object as the type there doesn't seem to work. Any ideas how I might be able to scan for this?

Mr.Misfit
Jan 10, 2013

The time for
SkellyBones
has come!
Further adventures with SSL/TLS and Visual Basic shenanigans in collusion with node.JS.

After asking my questions last night, I went to work. As you might remember from above, I tried to enter the CA-self-signed cert for a test into my certificate storage which...failed since I couldn´t actually create a correct .p12/equally valid acceptable file format from TinyCA because I´ve somehow misplaced the original CA password. That was bad. At that point I was close to giving up, but I´m nothing if not persistent. I then restarted the entire process from a newly created CA, exchanging all certificates from old CA to new CA, still self-signed but at least now I knew the password again. I then tried to connect. And...it didn´t work.

At first I was stumped. In fact the timeout remained. So I shook something in node.JS up and found that there was a problem with the node.JS server side. "Bad password in pem file" basically. I tripped over myself trying to solve this because as a hobbyist most of the lingo went straight over my head, but I tried anyway. As it turned out, all I needed to do was add the passphrase/-word for the certificate into the node.js options. Voíla, node.js server works, with new certificate et all. I then set it to rejectUnauthorized:false and tried a simple web request connect via my VB app. Connection worked out, he got the data, then my app crashed. At this point my thought process was basically "what...the hell?!" because suddenly something had broken, which before, worked perfectly.

You see, as part of my app I´m reading and deserializing a JSON object from the node.js server, which is then put into it´s own new database via SQLite. Of course, there has to be a database file for that to happen as well, and originally I´ve put in a SUB to make VB check for that. Somehow...that function call got lost somewhere in between, and now he was crashing whenever he tried to enter the results into the database he couldn´t find because it wasn´t being created. Argh. Another hour went by while I searched, found, yelled, and fixed the error, after which I finally went to focus my own attention back to the web request.

So far, I´m at the point where I need to authenticate the web-requesting app as a client via client-certificate to the node.js tls-secure server, who of course now has been put into the "rejectUnauthorized:true"-mode again, so that no data is being pushed through without authorization, but I´m kinda stumped on that bench.

If I understand it correctly, I can actually add the client certificate to the x509 certificate storage for the app itself, correct?

tl:dr: Problem with certificates fixed after much hair ripped out and am now trying to go client-certificate authorizes requesting application from localhost node.js server via x509-cert in VB....

edit: Also, I don´t know how one uses cURL. I´ve downloaded it from the website but ...well, beginner in all this et all :D
edit2: After running a trace.config.log feature I found online which forced System.Net to log everything it does into a log.file, I got some nice feedback. Apparently creating the SSL/TSL-connection is aborted because "neither of the certificates available fits the required one for the server, which is strange, because I´ve looked into TinyCA again and I´m quite sure that both the client as well as the server cert are signed by the same CA and should work out. There´s still something I´m missing here...hmmm

Mr.Misfit fucked around with this message at 21:45 on Jun 15, 2017

rarbatrol
Apr 17, 2011

Hurt//maim//kill.

Rocko Bonaparte posted:

I'm trying to be crazy with generics again.

I have a serialization framework for a personal Unity game project. I'm looking for implementations of the given generic factory interface:

(note that I stripped some descriptive text to flatten all this)
code:
public interface ISaveLoadFactory<TEntity, TComponent>
{
    object CreateSaveHandle(TComponent component);
    void LoadFromSerializer(object serializedHandle, TEntity parent, Dictionary<SceneObjectId, TEntity> objectMap);
    string GetSerializerName();
    Type GetRecordType();
    Type GetComponentType();
    List<TEntity> GetStrongReferencedEntities(TComponent component);

}
I made it generic because I've moved the code out of Unity into a separate library and I have a mock testbench for testing my internal logic is working. It turns out that most implementations of this interface do some pretty typical things, and I could nail it with a generic like this:

code:
public abstract class BasicSaveLoadFactory<TRecord, TEntity, TComponent> : ISaveLoadFactory<TEntity, TComponent>
{
    public object CreateSaveHandle(TComponent component)
    {
        return Save(component);
    }

    public Type GetComponentType()
    {
        return typeof(TComponent);
    }

    public Type GetRecordType()
    {
        return typeof(TRecord);
    }

    public string GetSerializerName()
    {
        return typeof(TComponent).ToString();
    }

    public List<TEntity> GetStrongReferencedEntities(TComponent component)
    {
        // Override if you actually need to implement this!
        return null;
    }

    public void LoadFromSerializer(object serializedHandle, TEntity parent, Dictionary<SceneObjectId, TEntity> objectMap)
    {
        var converted = (TRecord)serializedHandle;
        Load(converted, parent, objectMap);
    }

    public abstract void Load(TRecord record, TEntity parent, Dictionary<SceneObjectId, TEntity> objectMap);
    public abstract TRecord Save(TComponent component);
}
This collapses it down to a basic save/load call. In the LoadFromSerializer call. I thought all was good in the world, but my code to scan for factories won't pick up BasicSaveLoadFactory classes:

code:
    public static Dictionary<Type, ISaveLoadFactory<TEntity, TComponent>> GetFactoryMap()
    {

        // Regular factory lookup table
        var factoryLookup = new Dictionary<Type, ISaveLoadFactory<TEntity, TComponent>>();
        var rawFactoryTypes = System.AppDomain.CurrentDomain.GetAllDerivedTypes(typeof(ISaveLoadFactory<TEntity, TComponent>));
        foreach (var factoryType in rawFactoryTypes)
        {
            var instance = (ISaveLoadFactory<TEntity, TComponent>)Activator.CreateInstance(factoryType);
            factoryLookup.Add(instance.GetComponentType(), instance);
        }

        return factoryLookup;
    }
I tried also scanning for BasicSaveLoadFactory but I can't pick up anything. The big problem there is that I don't have TRecord and just stubbing in object as the type there doesn't seem to work. Any ideas how I might be able to scan for this?

I have a feeling that GetAllDerivedTypes might not sniff out implementations with specific generic type parameters. I vaguely remember trying to make something like that work... Maybe something like this?
https://stackoverflow.com/questions/18233390/check-if-a-type-implements-a-generic-interface-without-considering-the-generic-t

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

rarbatrol posted:

I have a feeling that GetAllDerivedTypes might not sniff out implementations with specific generic type parameters. I vaguely remember trying to make something like that work... Maybe something like this?
https://stackoverflow.com/questions/18233390/check-if-a-type-implements-a-generic-interface-without-considering-the-generic-t

Well, that is literally the problem--I think. There's a part 2 to this where I try to use Activator to instantiate these things. It should just work since all my TRecord types are traveling together in the application domain, but we'll see.

I tried to dip my nose into this a little bit last night, but it was way too late and I was way too stupid. I wound up with a situation where one of my BasicSaveLoadFactory types was coming up, the code was able to draw some relationship to an ISaveLoadFactory, but somehow the types were ever-so-slightly different. I had to dump what they both were from the VS2015 immediate window into text files, and then check them with KDiff3 to highlight what was different. Just about everything was identical, but there was one or two name changes that would fail and == check. I guess I have to do a pedantic reading of some of those type checking methods now.

Mr Shiny Pants
Nov 12, 2012
I got a question about Async and MVC5 and how to go about making this stuff work.

I am using MVC5 to create some controllers so I can do some CRUD operations on my server.

I am using a PCL that exposes some HTTP requests and responses that my MVC application uses to communicate with a different backend. The problem is that GetResponse() is missing from System.Net in a PCL and you only get BeginGetResponse and EndGetResponse. No worries, I've created a Async method that runs these operations and all is fine. Now the problem comes when calling these methods from MVC.

Is it okay to call Task.FromResult(AsyncMethod()).Result in my controllers ( the standard, scaffolded, methods are not marked async )? I know these questions have come up in the past, but I do find it hard to grok this stuff with all the ways you can shoot yourself in the foot with exceptions and the like.

I am tempted to just get the PCL HttpClient that someone wrote and just do it synchronously.

After some searching it seems like you can convert a controller to Async pretty easily: http://peterkellner.net/2015/12/01/converting-controller-method-mvc5-async/

Hope it doesn't break anything else.

Mr Shiny Pants fucked around with this message at 11:39 on Jun 17, 2017

SirViver
Oct 22, 2008
Can you give a simplified code example of what you're doing? Not quite sure I understand what's going on.

From what it sounds like:
  • You have a library that doesn't implement "real" async, so you've made it async with a custom wrapper, e.g. using Task<T>.Factory.FromAsync(...)
  • Your controller methods (the entry point of the MVC routing) are not marked async
If that is correct, there's a two problems with that - one practical, one philosophical (well, also practical, but we'll get to that in a minute).

First the practical one: async only works if it's async "all the way down". Any method marked as async whose returned Task is not also await-ed does not, in fact, run asynchronously at all. Thankfully converting the base controller methods to async is very easy: just add the async keyword to the method and wrap the return type in a Task. Finally make sure to await the task returned from your AsyncMethod(). MVC5 understands this and knows how to call your controllers asynchronously.


But the second, and at least to me more important question is: why are you using async at all? What benefits do you think you'll get from using it? Because with your current usage scenario, the answer to that is: none. In fact, the async code will be slightly less efficient, as the compiler has to construct all the extra black magic state machinery around it, only for the end result to be the same.

The crux in the matter is that your PCL does not offer a "real" async method, but that you had to construct one. To understand why this is a problem, you need to understand why anybody would use async in ASP.NET MVC to begin with: thread usage. After ASP.NET receives a request, the classic, non-async processing looks like this:
  1. ASP.NET takes a thread from the thread pool and starts processing the request (controller action) on it
  2. The action takes whatever amount of time it needs until it completes, keeping the thread "in use" during that time
  3. The result is sent to the client and the thread is returned to the thread pool
With async, it works like this:
  1. ASP.NET takes a thread from the thread pool and starts processing the request (controller action) on it
  2. The action hits the await statement and returns control immediately. An I/O Completion Port is registered and the worker thread is returned to the thread pool
  3. Once the async operation completes, the IOCP is signaled. Another thread is drawn from the thread pool to finish processing the request
  4. The result is sent to the client and the thread is again returned to the thread pool
The difference is that with async a thread pool thread was only used for the minimal amount of time necessary, and not kept around essentially twiddling its thumbs waiting for the potentially long running action (like HTTP requests to different systems) to complete. The reason this is significant is that the ASP.NET thread pool is limited, limiting the maximum amount of concurrent requests it can process without having to queue them. Using async returns these threads while they are not needed (during slow, non-CPU bound I/O calls), allowing them to be used for handling other requests in the meantime.

Now why do I call all this pointless just because you wrote your own wrapper around the PCL? Because you cannot (easily) do thread-less async yourself. Whatever wrapper you wrote around the BeginGetResponse() and EndGetResponse() calls inevitably uses a thread to do the asynchronous waiting, and unless you actually manually started a new thread (=slow) that thread will be pulled from the very same thread pool ASP.NET uses to process requests. So in the end you've added a whole lot of complexity (albeit mostly hidden) and gained nothing, as you'll still on average block one thread pool thread for processing one request - the work is just performed on different threads this time.

Further reading for general async understanding:
Implementing the Task-based Asynchronous Pattern
There Is No Thread

SirViver fucked around with this message at 13:11 on Jun 17, 2017

Mr Shiny Pants
Nov 12, 2012
Sure. In the regular System.Net namespace there is a WebRequest class that has a method called GetResult. In a PCL class this method does not exist. Only BeginGetResponse and EndGetResponse, to get this to work you need to use something
like AsyncCallBack in your method, making the return something like IAsyncResult.

How would you create this method? This has forced me to construct an "async" method in my PCL. Now I don't pretend to know everything about this, but all examples I've seen thus far have used TaskFactory to create the methods.

I've been working some more on this and now have the following:

In the PCL:

code:

    let private getFoo() =
        async {
            try
                let request = WebRequest.Create(serverUrl + "/foo") :?> HttpWebRequest
                request.Method <- "GET"
                use! response = Async.FromBeginEnd(request.BeginGetResponse,request.EndGetResponse)
                use reader = new StreamReader(response.GetResponseStream())
                let result = JsonConvert.DeserializeObject<System.Collections.Generic.List<foo>>(reader.ReadToEnd())
                return result
            with
            | _ -> return new System.Collections.Generic.List<foo>();
        }

    let GetFooAsync() =
        getFoo() |> Async.StartAsTask
In my controller:

code:
public async Task<ActionResult> Index()
{
        var foos = await Proxy.GetFooAsync();
	return View(foos);
}
Proxy is the PCL in the above code.
To be honest, I did not want to have any async stuff in this PCL, like you said there is no need, but the omission of a regular GetResponse() method forced me to look at the Task Library leading me into this rabbit hole.

Mr Shiny Pants fucked around with this message at 14:10 on Jun 17, 2017

Sab669
Sep 24, 2009

Edit; never mind...

Sab669 fucked around with this message at 21:06 on Jun 19, 2017

dougdrums
Feb 25, 2005
CLIENT REQUESTED ELECTRONIC FUNDING RECEIPT (FUNDS NOW)
Is there a simple way to get a .net core 2 console program to use the server GC? What magical file do I have to add to get it to be copied into the build runtime config? Right now I am literally overwriting the runtime config that the build generates and restarting the program ...

SirViver
Oct 22, 2008
Sorry for the late response. I'm really not familiar with F# handling of async.

I've just created a test PCL to see what exactly is available, and you're right, WebRequest does not expose a GetResponse() method. But it does expose a proper GetResponseAsync() one, which, if you use that, would make the use of async throughout your controller actually useful.

I can only give you an example in C#, but this is how I'd probably write the PCL:
C# code:
public class MyPCL
{
	//...

	public List<Foo> GetFoo()
	{
		var request = WebRequest.Create(serverUrl + "/foo");
		request.Method = "GET";

		var asyncResult = request.BeginGetResponse(null, null);
		asyncResult.AsyncWaitHandle.WaitOne();

		using (var response = request.EndGetResponse(asyncResult))
		using (var reader = new StreamReader(response.GetResponseStream()))
		{
			return JsonConvert.DeserializeObject<List<Foo>>(reader.ReadToEnd());
		}
	}

	public async Task<List<Foo>> GetFooAsync()
	{
		var request = WebRequest.Create(serverUrl + "/foo");
		request.Method = "GET";

		using (var response = await request.GetResponseAsync().ConfigureAwait(false))
		using (var reader = new StreamReader(response.GetResponseStream()))
		{
			return JsonConvert.DeserializeObject<List<Foo>>(reader.ReadToEnd());
		}
	}
}
Obviously the thing is grossly simplified/incomplete and does zero error handling, but this should allow to to expose a classic synchronous GetFoo() method and a proper async GetFooAsync() one. That said, I do not really have much practical experience with async either, and that code above is of course not tested at all.

The reason I have two separate implementations here is that 1) I assume you still need a synchronous version and don't want to rewrite all callsites, and 2) everywhere I look I find that creating a simple synchronous wrapper around GetFooAsync() (like shown below) is potentially a Bad Idea™.

It might be OK to use something like this...
C# code:
	public List<Foo> GetFoo()
	{
		return GetFooAsync().Result;
	}
...due to using ConfigureAwait(false) in the async method, but I'm not 100% sure.

Mr Shiny Pants
Nov 12, 2012
Thanks, no worries. :)

Would you believe my mind is so wired looking for MethodNameAsync that I totally did not see AsyncGetResponse?

I am using the Begin and End stuff right now and it seems to work with Async controllers pretty well. If I come across anything that does not work I might rework it.

Thanks for the help! Yeah the F# stuff is me throwing myself in the deep end trying to use it in as many ways as possible. MVC5 in F# was a bit much, but the proxy stuff works pretty well.

Magnetic North
Dec 15, 2008

Beware the Forest's Mushrooms
Sorry that I don't have code to share to accompany this question, but I can't access SA at work.

I am still sort of a WPF / MVVM novice, and I've gotten tripped up on a complicated request. They want to have a control that is reusable by multiple similar devices. We'll call the UserControl in question DeviceControl and the devices Foo and Bar. So, the Main window hosts something I'll just call GroupControl, which has its own ViewModel, but it is basically just a Groupbox with a DataGrid that binds to an ObservableCollection. In that codebehind is just the normal this.DataContext = localVM object. Now, that collection was (originally) of DeviceControlViewModels, which I had given a constructor that could accept the actual device as a parameter. However, after the instances of the VM with Foo and Bar were added to the collection, something (could not figure out what) was re-calling the DeviceControlViewModel class and blanking them since it no longer had the parameter. I tried changing it so that it was a collection of devices instead but I ran into problems getting the UserControls to bind to Foo and Bar. So I'm clearly doing something wrong.

My Googling for this didn't really bear fruit. I couldn't find anyone who had nested VMs this way, except one company that seemed to be selling something to make it possible / easier. My original thought was that maybe there's a reason for that and you can't nest ViewModels like that because the datacontext gets confused. Still, the only solutions I read were, "Put it in the codebehind, it's fine, sweep it under the rug, gently caress it." Though now that I am typing this all up, I'm thinking that having a collection of VMs is a bad idea. At the same point, I don't know how to build what they are asking for. Maybe it would be possible to just make the first wrapper groupbox usercontrol think into part of the actual DeviceControl to skip a VM, if that turns out to be the problem?

Honestly, typing that up has already helped me, but does anyone have any insight on my terrible Inception-style view models?

GoodCleanFun
Jan 28, 2004

Magnetic North posted:

Sorry that I don't have code to share to accompany this question, but I can't access SA at work.

I am still sort of a WPF / MVVM novice, and I've gotten tripped up on a complicated request. They want to have a control that is reusable by multiple similar devices. We'll call the UserControl in question DeviceControl and the devices Foo and Bar. So, the Main window hosts something I'll just call GroupControl, which has its own ViewModel, but it is basically just a Groupbox with a DataGrid that binds to an ObservableCollection. In that codebehind is just the normal this.DataContext = localVM object. Now, that collection was (originally) of DeviceControlViewModels, which I had given a constructor that could accept the actual device as a parameter. However, after the instances of the VM with Foo and Bar were added to the collection, something (could not figure out what) was re-calling the DeviceControlViewModel class and blanking them since it no longer had the parameter. I tried changing it so that it was a collection of devices instead but I ran into problems getting the UserControls to bind to Foo and Bar. So I'm clearly doing something wrong.

My Googling for this didn't really bear fruit. I couldn't find anyone who had nested VMs this way, except one company that seemed to be selling something to make it possible / easier. My original thought was that maybe there's a reason for that and you can't nest ViewModels like that because the datacontext gets confused. Still, the only solutions I read were, "Put it in the codebehind, it's fine, sweep it under the rug, gently caress it." Though now that I am typing this all up, I'm thinking that having a collection of VMs is a bad idea. At the same point, I don't know how to build what they are asking for. Maybe it would be possible to just make the first wrapper groupbox usercontrol think into part of the actual DeviceControl to skip a VM, if that turns out to be the problem?

Honestly, typing that up has already helped me, but does anyone have any insight on my terrible Inception-style view models?

Collections of viewModels works very well if you have it setup correctly. I've posted a few times about this in this thread with examples, check my history.

biznatchio
Mar 31, 2001


Buglord

dougdrums posted:

Is there a simple way to get a .net core 2 console program to use the server GC? What magical file do I have to add to get it to be copied into the build runtime config? Right now I am literally overwriting the runtime config that the build generates and restarting the program ...

Add this property to the PropertyGroup in your csproj:

code:
<ServerGarbageCollection>true</ServerGarbageCollection>
Older versions (not sure what version it changed) required it to be set in a runtimeconfig.template.json file instead:

code:
{
  "gcServer": true,
  "System.GC.Server": true,
  "gcConcurrent": true
}

Mr Shiny Pants
Nov 12, 2012
What is a smart way to compare properties? I have a F# record type that has some properties, some of these might be changed by a user and I want to find out which.
I now just recreate the object and fill all the properties again, which is fine. If it comes through my validation phase the values are all ok and I need them to be stored anyway.

The problem is that one field is getting reverse geocoded and I don't want to hit the webservice again if the field is not changed.
Iterating with reflection over all the properties sounds icky, but I can see the value in just treating all properties as a map and just choosing the one's that are different to the source object.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

Mr Shiny Pants posted:

What is a smart way to compare properties? I have a F# record type that has some properties, some of these might be changed by a user and I want to find out which.
I now just recreate the object and fill all the properties again, which is fine. If it comes through my validation phase the values are all ok and I need them to be stored anyway.

The problem is that one field is getting reverse geocoded and I don't want to hit the webservice again if the field is not changed.
Iterating with reflection over all the properties sounds icky, but I can see the value in just treating all properties as a map and just choosing the one's that are different to the source object.

I'm guessing those records are exposed to the C# environment as [<CLIMutable>], which is the reason you're worried about normally-immutable records changing?

In any case, reverse geocoding sounds like something where you'd want to keep a global result cache anyway. The data size is tiny (float * float -> string), so a simple memoization pattern with a ConcurrentDictionary<_,_> cache (for thread safety) ought to work.

Mr Shiny Pants
Nov 12, 2012

NihilCredo posted:

I'm guessing those records are exposed to the C# environment as [<CLIMutable>], which is the reason you're worried about normally-immutable records changing?

In any case, reverse geocoding sounds like something where you'd want to keep a global result cache anyway. The data size is tiny (float * float -> string), so a simple memoization pattern with a ConcurrentDictionary<_,_> cache (for thread safety) ought to work.

No, they are changeable records with the {record with property = new value } syntax. I have some things stored in Lists and they can be updated by some commands. Should I be doing this differently?

code:
let compare original updated =
    Array.map2(fun (x:PropertyInfo) (y:PropertyInfo) -> if  x.GetValue(original) = y.GetValue(updated) then x.GetValue(original) else y.GetValue(updated)) 
(FSharpType.GetRecordFields(original.GetType())) (FSharpType.GetRecordFields(updated.GetType()))
    |> ( fun x -> Activator.CreateInstance(original.GetType(),x))
This works, but I think I am being a bit too smart for myself here. I wrote it just to see if I could. That cache is a nice idea BTW, I might just steal that. :)

Edit: I just came to the realisation that I don't need to update the existing record, if the new record ( the updated one ) validates fine, I can just remove the old one and put in the new one without needing to compare anything.... All the required fields come in anyway......

Crap.

Mr Shiny Pants fucked around with this message at 17:24 on Jun 24, 2017

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

quote:

let compare original updated =
Array.map2(fun (x:PropertyInfo) (y:PropertyInfo) -> if x.GetValue(original) = y.GetValue(updated) then x.GetValue(original) else y.GetValue(updated))
(FSharpType.GetRecordFields(original.GetType())) (FSharpType.GetRecordFields(updated.GetType()))
|> ( fun x -> Activator.CreateInstance(original.GetType(),x))

... isn't this just a very, very complicated way of doing:

code:
let compare _ updated = updated
?

Mr Shiny Pants
Nov 12, 2012

NihilCredo posted:

... isn't this just a very, very complicated way of doing:

code:
let compare _ updated = updated
?
I am retarded. Something for the coding horrors I guess.

I was so hell-bent on only updating the existing properties with the changed one's from the existing record, I totally lost track of what my goal was or something......

In my defense, I was trying to update the record in place using a field name with reflection, that does not work unless you add CLIMutable on the record I think. Then I had brainfart and instanced a new one, because that did work. Making it redundant. :)

Mr Shiny Pants fucked around with this message at 18:00 on Jun 24, 2017

mystes
May 31, 2006

Is there some way to use the NEST c# elasticsearch API without tons of crazy lambda expressions? I'm talking about stuff like:
code:
searchResponse = client.Search<Project>(s => s
   .Query(q => q
       .Bool(b => b
           .Filter(bf => bf
               .DateRange(r => r
                   .Field(f => f.StartedOn)
                   .GreaterThanOrEquals(new DateTime(2017, 01, 01))
                   .LessThan(new DateTime(2018, 01, 01))
               )
           )
       )

   )
);
I assume this is a side effect of providing a "fluent" API in c# but it seems pretty awful to me.

Actually, in general the API seems way crazier/dumber than the python one. There are also like 5 different ways to specify property mappings for objects, and for some reason the documentation doesn't seem to like to discuss the only one that seems to be even remotely readable (using attributes).

Edit: Oh never mind. It does seem like an alternative does exist, although there don't seem to be as many examples for it. Argh, it looks like if you use that syntax you just end up entering stuff as strings without type safety, though.

mystes fucked around with this message at 01:11 on Jun 26, 2017

Mr Shiny Pants
Nov 12, 2012
In my F# code I have a HttpRequest coming in to get something from my server. Chrome will cancel requests when a resource is no longer needed, when my application wants to write to the aforementioned requeststream it can't anymore because it has been closed by Chrome.

I've tried adding a try catch statement around this block, but VS will still break on it. I read that this is because the exception is in framework code ( System.dll System.Net.Sockets.SocketException ) so that makes sense when "Just my code" is enabled.

Now I have disabled "Just my code" and it still won't continue into my exception handler. Why is this, anybody know?

EssOEss
Oct 23, 2006
128-bit approved

Mr Shiny Pants posted:

so that makes sense when "Just my code" is enabled.

No it doesn't and post some code.

Mr Shiny Pants
Nov 12, 2012

EssOEss posted:

No it doesn't and post some code.

Well according to this: http://apollo13cn.blogspot.nl/2012/05/debug-async-f-trycatch-statement.html

It is something that happens, and I also came across this one:

https://stackoverflow.com/questions/8722062/f-async-frombeginend-not-catching-exceptions

The code is not the same, but the result is:

code:
    let private getFooById id =
            async {
            try
                let request = WebRequest.Create(serverUrl + "/foo/" + id.ToString()) :?> HttpWebRequest
                request.Method <- "GET"
                use! response = Async.FromBeginEnd(request.BeginGetResponse,request.EndGetResponse)
                use reader = new StreamReader(response.GetResponseStream())
                let result = JsonConvert.DeserializeObject<FooModel>(reader.ReadToEnd())
                return result
            with
            | _ -> return new FooModel()
        }
This makes visual studio break on a Unhandled Exception because of a connection fail, if I understand correctly, it jumps into the EndGetResponse before it bubbles up. My other code is because of a client disconnection when writing to a stream.

Mr Shiny Pants fucked around with this message at 22:26 on Jun 27, 2017

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

Does replacing the try block with Async.Catch help?

Mr Shiny Pants
Nov 12, 2012

NihilCredo posted:

Does replacing the try block with Async.Catch help?

I will try this. It works without Visual Studio though......

The code, in short, is a HttpRequest comes into the server, it kicks it off into an async workflow using Async.Start and starts listening again for a connection. I am not really concerned about the outcome of one particular request, just that it keeps chugging along.

Mr Shiny Pants
Nov 12, 2012
I am probably late to the party, but websockets are pretty freaking cool.

I was looking for a way to notify my clients if something has been added or changed in the db and having them poll every couple of minutes seemed lame, so I thought: "Why not push notifications to them, I'll use this new fangled thing called websockets!".
After checking out SignalR and thinking it pretty complicated I came across websocket-sharp and that seemed much easier.

After 10 minutes of work I now have a websocket server running, have a listenchannel in Npgsql defined and receive Postgres notifications in my browser using a Websocket client for Firefox. All running in FSI.exe.
I am pleasantly surprised.

mystes
May 31, 2006

.NET Core 2.0 Preview 2 has been released, and f# appears to be working again for the moment.

Adbot
ADBOT LOVES YOU

JerikTelorian
Jan 19, 2007



I've got a complicated question (at least, it seems complicated). I'm working in C# and Unity.

I'd like to create a UI element that displays some information from a class. For example, a text element that prints the HP of mob. I'd also like that UI element to change the information it prints -- maybe you want it to display the MP instead of HP, or the level, and to make this change while the software is running.



Maybe put a better way: is there a way, at runtime, to identify the properties exposed by a class? Is there a way for me to show the player, while the game is running, that gameClass has HP, MP, level, and other exposed and to change a UI element to display one of those?

I know this is awkwardly put, but I'm sort of struggling to find a good way to explain what I want to do. I want the player to be able to display one of those ints in gameClass, but I want them to be able to choose. I'm trying to figure out if there is a good way to do this that also allows for me to readily modify gameClass and add new values.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply