|
|
Thanks, I'll look into it
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Hello all. While trying to implement a web-socket handshake, I encountered a weird behavior. It looks like the HttpListenerResponse class doesn't send the 'Connection' header. Here is an example for explaining what I mean:
public void TestWebSocketHttpHandshake()
{
int port = 9444;
ManualResetEvent serverStartedEvent = new ManualResetEvent(false);
ManualResetEvent clientClosedEvent = new ManualResetEvent(false);
async Task RunHttpServer()
{
HttpListener hl = new HttpListener();
hl.Prefixes.Add($"http://+:{port}/");
hl.Start();
serverStartedEvent.Set();
HttpListenerContext hlc = await hl.GetContextAsync();
string secWebSocketKeyHeader = hlc.Request.Headers["Sec-WebSocket-Key"]?.Trim();
string secWebSocketAcceptHeader = Convert.ToBase64String(
System.Security.Cryptography.SHA1.Create().ComputeHash(
Encoding.UTF8.GetBytes(secWebSocketKeyHeader + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
)
);
hlc.Response.StatusCode = (int)HttpStatusCode.SwitchingProtocols;
hlc.Response.StatusDescription = "Switching Protocols";
hlc.Response.ProtocolVersion = new Version("1.1");
hlc.Response.AddHeader("Upgrade", "websocket");
hlc.Response.AddHeader("Connection", "Upgrade");
hlc.Response.AddHeader("Sec-WebSocket-Accept", secWebSocketAcceptHeader);
hlc.Response.Close();
clientClosedEvent.WaitOne();
hl.Stop();
}
async Task RunTcpClient()
{
const string eol = "\r\n";
serverStartedEvent.WaitOne();
using (TcpClient tc = new TcpClient())
{
tc.Connect("localhost", port);
using (NetworkStream ns = tc.GetStream())
{
string wsRequest =
$"GET /chat HTTP/1.1{eol}Host: localhost:{port}{eol}"+
$"Upgrade: websocket{eol}Connection: Upgrade{eol}" +
$"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=={eol}"+
$"Sec-WebSocket-Version: 13{eol}{eol}";
byte[] wsRequestBytes = Encoding.ASCII.GetBytes(wsRequest);
await ns.WriteAsync(wsRequestBytes, 0, wsRequestBytes.Length);
Console.WriteLine("Sent request:");
Console.WriteLine(wsRequest);
byte[] responseBuf = new byte[256];
int resBytesCount = await ns.ReadAsync(responseBuf, 0, responseBuf.Length);
string wsResponse = Encoding.ASCII.GetString(responseBuf, 0, resBytesCount);
Console.WriteLine("Received response:");
Console.WriteLine(wsResponse);
}
}
clientClosedEvent.Set();
}
Task.WaitAll(RunHttpServer(), RunTcpClient());
} The result is:
Sent request:
GET /chat HTTP/1.1
Host: localhost:9444
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Received response:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Content-Length: 0
Server: Microsoft-HTTPAPI/2.0
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Date: Mon, 11 Feb 2019 16:16:37 GMT So, what we can see here is that we have a HttpListener server that sets the 'Connection' header in the response but, when the client gets the server's response, the 'Connection' header is missing. I know that we can use the HttpListenerContext.AcceptWebSocketAsync method for handling the web-socket connection but, this method uses the operating system web-socket support that is supported only from Windows 8/ Windows Server 2012 and, we want this to work also on a Windows Server 2008 system. I know that there are some solutions on the web for running a web-socket server. But, all the solutions I found are for running a server that listens to web-socket requests on a given port. Since in my case I want to accept web-socket requests on the same port of an existing server (Owin server that does other things), I have to handle it using the given request's HttpListenerContext . Can anyone explain this behavior (the missing 'Connection' header) or, suggest a solution?
modified 11-Feb-19 14:27pm.
|
|
|
|
|
I'm working on an app that hits a Web API. Right not I'm developing in VS2017 using it's local IIS. Can I somehow configure this so that other PC's can access that web API for testing purposes?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
|
I went through his blog right before I posted. After adding the binding line to the .config, then running my app, I get
"Process with an Id of [some id] is not running."
Here's my config entries
<site name="RemoteServices.BusinessServices" id="6">
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\Projects\RemoteServices.BusinessServices" />
</application>
<bindings>
<binding protocol="http" bindingInformation="*:53175:localhost" />
<binding protocol="http" bindingInformation="*:53175:192.168.51.66"
</site>
I closed an reopened vs and my web api project failed to load. Commented out the line in the .config and everythign is back to normal.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Kevin Marois wrote: <binding protocol="http" bindingInformation="*:53175:192.168.51.66" //<I added this
Is that a typo in your question, or did you really miss out the closing /> from that element?
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Yes, it was a typo. Fixed it and all works as expected.
Thank you again
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Richard,
I'm back to this again. I had this working and now it doesn't.
I went back & checked my work. I did the following:
IIS Config
<bindings>
<binding protocol="http" bindingInformation="*:53122:localhost" />
<binding protocol="http" bindingInformation="*:53125:192.168.51.66" />
</bindings>
I also ran
netsh http add urlacl url=http:
netsh advfirewall firewall add rule name="ePlex Remote Services" dir=in protocol=tcp localport=53125 profile=private remoteip=localsubnet action=allow
When I run the web api from my dev pc it works fine. But when I try to hit 192.168.51.66:53125 from another PC it can't find it.
I'm not sure how to debug this. Any thoughts?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Is the API project running when you try to access it from the remote PC?
Is the firewall's "private" profile active?
Is the remote PC on the same local subnet as your dev PC?
Try turning on logging for the firewall to see if that gives you any information:
How to Track Firewall Activity with the Windows Firewall Log[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Well, I fixed it, but I don't know what was wrong.
First, I went through all your suggestions. Still couldn't get it to work.
So I removed & recreated the Web API project, ran the steps from that blog, and bingo - back & and accessable remotely again.
Thanks for your help again.
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I'm trying to call a method on my Operator controller called AddOperator
[HttpPost]
public void AddOperator(OperatorEntity entity)
{
var bl = GetBusinessLayer();
bl.Add(entity);
}
RestClient baseURl is "{http://localhost.fiddler:53175/api}"
The RestRequest.Resource is "/Operator/AddOperator/".
The RestRequest.Parameters collection has one entry which is an instance of the OperatorEntity.
Fiddler Output
GET http:
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml, text/plain
User-Agent: RestSharp/106.6.7.0
Host: localhost:53175
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Notice the GET in the output.
I'm really new to WebAPI's, but I thought that I needed to mark the controller method with [HttpPost] , yet that doesn't seem to work.that
What am I doingwrong here?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
You do need to mark the method with [HttpPost] (or technically, [HttpPut] if this is a REST API).
The client call is using the wrong HTTP method.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
ya, that was it. Thank you sir!
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I'm working on a WPF app against an ASP.Net MVC Web API.
I'm trying to implement a delete in my Operator controller. I'm getting
System.Exception: 'An error occured calling the WebAPI.
The status code is 'MethodNotAllowed'.
The error message is {"Message":"The requested resource does not support http method 'DELETE'."}'
Client Side Proxy
public async Task DeleteOperatorAsync(Guid id)
{
await Task.Factory.StartNew(() =>
{
var webAPIExecutor = new WebAPIExecutor(ServerUrl, "/Operator/Delete/", Method.DELETE);
webAPIExecutor.AddParameter(id, "id");
webAPIExecutor.Execute();
});
}
Controller
[HttpDelete]
public void Delete(Guid id)
{
IBusinessLayer bl = new BusLayer();
bl.DeleteOperator(id);
}
The class WebAPIExecutor is working fine for all other calls so it's most likely not the problem, but I can post it if someone wants to see it.
Fiddler shows this info
DELETE <a href="http://localhost:53175/api/Operator/Delete/">http:
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml, text/plain
User-Agent: RestSharp/106.6.7.0
Content-Type: application/json
Host: localhost:53175
Content-Length: 38
Accept-Encoding: gzip, deflate
"77932bef-1b12-4204-9bd7-9a50f854a72a"
All other Web API calls are working. Canyone know what's wrong?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
I suspect it's because you're passing the parameter in the request body, rather than in the URL:
ASP.NET web API HTTP Delete 405 Method Not Allowed - Stack Overflow[^]
You might need to add the [FromBody] attribute to your parameter:
Using [FromBody] | Parameter Binding in ASP.NET Web API | Microsoft Docs[^]
Slightly off-topic:
public async Task DeleteOperatorAsync(Guid id)
{
await Task.Factory.StartNew(() =>
{
var webAPIExecutor = new WebAPIExecutor(ServerUrl, "/Operator/Delete/", Method.DELETE);
webAPIExecutor.AddParameter(id, "id");
webAPIExecutor.Execute();
});
}
That just looks nasty. It would be better to make your WebAPIExecutor class expose async methods. The Execute method is IO-bound, not CPU-bound, so pushing the work onto a background thread doesn't make much sense.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
That did it. I set the FromBody attrib and it worked.
As far as the Executor, here's the Execute code:
public void Execute()
{
URL = client.BaseUrl + request.Resource;
IRestResponse result = null;
try
{
result = client.Execute(request);
int resultCode = (int)result.StatusCode;
if (resultCode > 299)
{
string message = string.Format("An error occured calling the WebAPI. {0} The status code is '{1}'. {2} The error message is {3}",
Environment.NewLine, result.StatusCode, Environment.NewLine, result.Content);
throw new Exception(message);
}
}
catch (Exception e)
{
throw e;
}
}
Not sure what in here I could await. The RestClient doesn't expose any async methods.
Your thoughts?
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Is that RestSharp[^]?
If so, there's an ExecuteTaskAsync method that would work:
RestSharp/RestClient.Async.cs at 64357df6f8c428f3b39e78ab4b3034596dd2e953 · restsharp/RestSharp · GitHub[^]
Also:
Quote:
catch (Exception e)
{
throw e;
}
Don't do that. You've just thrown away the stack trace of the exception. If you have to catch and rethrow, just use throw; instead of throw e; . But in this case, since you're not doing anything with the exception, you can just remove the try..catch block.
And:
Quote:
throw new Exception(message);
I wish Microsoft had made the Exception class abstract ; there's never a good reason to throw new Exception(...); instead of using a more specific exception type.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Richard Deeming wrote: If so, there's an ExecuteTaskAsync method that would work:
You're right. Not sure why I didn't se that.
As far as the rest... we're just prototyping right now, so I'm throwing just in the interim. We'll be adding in more robust exception handling later.
Thanks for all your help
If it's not broken, fix it until it is.
Everything makes sense in someone's mind.
Ya can't fix stupid.
|
|
|
|
|
Hello everyone.
I have a asp.net core 2.1 project, where i need to use the adfs as an external authentication provider.
I just can't find a working solution and i'm getting a little bit desperate, so can anyone please help me!
Prefereably i'm looking for a solution via Oauth2 protocol.
I found one working solution with WS-federation (cookie based) - LINK, the authentication work just fine, the app first checks if an user is logged in, if not it redirects to adfs external login page and after a successful login it redirects back to the app and shows the data. There is just one small problem, i don't know how to get user info (user id, upn ...).
Thank you in advance and have a nice day.
.
|
|
|
|
|
Caveat - I don't use oAuth.
_dk6607 wrote: i don't know how to get user info (user id, upn ...).
I would think you would just get the fact that the user is authenticated/Authorised as a return from the external logon. UserID and password should not be available.
Never underestimate the power of human stupidity -
RAH
I'm old. I know stuff - JSOP
|
|
|
|
|
If you looked at the article from the link, you would see you can get a lot of information about the user, who has logged in, dependes on the configuration on the adfs.
The adfs communicates with ad (active directory) and gets the user info back as claims. Then the adfs returns data to the app as an encrypted token.
Here is the problem, i don't know how to solve, get the claims out of the token.
|
|
|
|
|
|
I've been googling this topic and I'm finding conflicting messages regarding which one to choose, as well as in CRaP ( Core Razor Pages ).
I suspect that Microsoft will abandon MVC in the next year or so, so there is that concern.
Organizationally speaking, CRaP is easier on the solution explorer browsing.
I read one view that said MVC is better for large apps, and CRaP was better for small single-page apps, but I read another item that says MVC doesn't scale as well as CRaP.
----------------
Regarding CRaP:
There appear to be two ways to "compartmentalize" large sites:
0) Add an Areas folder in the project root (requires a few settings changes in the app to allow areas)
1) Add a Features folder to the (generated) Pages folder
It seems to me that either is viable, but I'm wondering which would be "better", and why.
---------------------
Apparently you can mix/match MVC and CRaP, but I want to avoid doing that (to mitigate complexity), thus rendering that possibility off-topic for this thread.
Discuss...
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
John Simmons / outlaw programmer wrote: I suspect that Microsoft will abandon MVC in the next year or so, so there is that concern.
They've barely abandoned WebForms, so I seriously doubt they'll be chucking MVC under the bus any time soon.
Also, it's all "open source" now, so it would be much harder for Microsoft to abandon the project if the community still wants to keep it running.
John Simmons / outlaw programmer wrote: I read another item that says MVC doesn't scale as well as CRaP.
Were they comparing CRaP to "Core" MVC, or MVC5? I've seen lots of talk about Core being faster than MVC5 - and potentially getting even faster when they bring it back in-process in IIS - but I've not seen anyone suggesting that there's a difference between Core MVC and CRaP.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|