I am building a website that is managed over Microsoft IIS. I want my whole website to work like this:
The IIS gets a HTTP request over port 80 for the main website and then answers with the HTML and JS documents. These documents remain static and are simply saved as files on the server, which the IIS reads and send to the client without further modifying it.
In the JS document that the client gets, there are fetch()-commands that send additional requests during runtime over a different port when the user is interacting with the website. The browser should get back JSON data from the server. I have written a ASP.NET web application to do this.
This is what my current setup in IIS looks like:
enter image description here
I have set up a site for step one (front-end) and one for step two (back-end). I added a binding for the first site to port 80 and set the default document. I linked the second site to the directory in which the build binary of my ASP.NET application lies. Then, I added the binding with Port 5000 and the same IP-Address to the second site.
Step one works. When sending a request over Port 80, I get the website documents. But the second step doesn't. In debugging mode of Visual Studio, it works fine and it does it job. But I didn't manage to get step two working in IIS yet. The response I get when sending my requests is a 404. I created an additioonal controller to my back-end for testing that should just respond some hardcoded strings and do nothing more. Actually that works. I do get a 200 and the strings as a response. So there must be something wrong with the ASP.NET back-end communicating with my database.
I found out that everytime, when sending my request, an error log is written by my back-end. It says:
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware1
An unhandled exception has occurred while executing the request.
System.Text.Json.JsonException: A possible object cycle was detected which is not supported. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32.
at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializerCycleDetected(Int32 maxDepth)
at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|27_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
Again, I do not get the error when debugging the back-end ap
Can someone help?
The problem was basically wrong SQL Server permission setup. I managed to solve my problem. This may be helpful to people who are facing similar problems:
The "JsonException object cycle" error itself was not that helpful at all. So, I went into further debugging. I attached VisualStudio Debugging to the actual running IIS process like so: https://learn.microsoft.com/en-us/visualstudio/debugger/attach-to-running-processes-with-the-visual-studio-debugger?view=vs-2019
This was helpful for finding the reason for the error, as I could now experience log messages that were much more fitting to the actual error. Mind that you have to change the hostingModel to "outofprocess" in the web.config in order to attach to the standalone .Net process. https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/out-of-process-hosting?view=aspnetcore-5.0
In case you are using SQL Server Management Studio, create a login for "NT Authority" (Object Explorer > Security > Logins > NT-Authority), grant access to your database and make sure that you do not select a "deny" role in user mapping, because I did so, and that was causing my error.
Related
I am programming a fullstack application which is used on festivals to monitor their inventory on bars (how many bottles of gin they have for instance). It allows for creating an transfer request to get more stuff to specific bar and looking up those requests. The problem arises when the connection is slow enough to cause a timeout (by my testing at 1KB/s upload/download throttle it took approx 10s) but still send the data to the API.
My method which handles writing the data to the database looks like this:
public IActionResult WriteStorageTransfer([FromBody] StorageTransfer transfer)
{
Console.WriteLine("Started the execution of method");
var transferId = database.CreateNewDoc(transfer);
foreach (var item in transfer.items)
{
var sql = #$"insert into sklpohyb(idsklkarta, iddoc, datum, pohyb, typp, cenamj, idakce, idbar, idpackage, isinbaseunit)
values ({item.id}, {transferId}, current_timestamp, {packMj}, {transfer.typ}, {item.prodejnicena}, {transfer.idakce}, {transfer.idbar}, case when {pack.idbaleni} = -1 then NULL else {pack.idbaleni} end, {pack.isinbaseunit})";
database.ExecuteQueryAsTransmitter(sql);
}
return Ok(transferId); // transferId is then used by frontend to display the created transfer request.
}
This would be all nice and all, but the frontend appears to send the data to the API, API processes it and writes it to the database, but then timeout occurs on the HttpRequest, crashing the method, thus never returning a HttpResponse to the frontend (or returning code 0: 'Unknown error').
The exception thrown by the API:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
An unhandled exception has occurred while executing the request.
System.IO.IOException: The request stream was aborted.
---> Microsoft.AspNetCore.Connections.ConnectionAbortedException: The HTTP/2 connection faulted.
--- End of inner exception stack trace ---
at System.IO.Pipelines.Pipe.GetReadResult(ReadResult& result)
at System.IO.Pipelines.Pipe.GetReadAsyncResult()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2MessageBody.ReadAsync(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 destination, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.ReadFromStreamAsync(Stream utf8Json, ReadBufferState bufferState, CancellationToken cancellationToken)
at System.Text.Json.JsonSerializer.ReadAllAsync[TValue](Stream utf8Json, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object valu
e, Object container)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location ---
The size of the JSON sent to API is usually ~10 KB, nothing too serious like 100MB so I don't think the size is the problem
This leaves the frontend hanging and the users tend to click the button again, possibly writing multiple duplicates to the database as he does not know if the invoice has been processed or if there is an error in the app.
Interestingly the Console.Write("Started execution of the method") does not get triggered as I do not see it in the console window, yet the data gets written into the database after manually checking it.
Perfect thing would be if I could notify the user that something went wrong in the creation of the transfer request, and prevented the creation of it in the database. I tried using try catch block targeted on IOException
Thanks a lot in advance, anything goes at this point
The problem arises when the connection is slow enough to cause a timeout but still send the data to the API.
Back to the drawing board (or time to give us more details). If your POS app (which I assume this is) wants to report a sale to the back-end, why would the user have to wait for this? And why would the user be able to report one sale twice?
Instead have the client generate a unique transaction ID locally and store them in local storage, and (after each sale, and periodically, but most importantly: on the background) have the client try to synchronize their transactions to the server. The server can then reject duplicate transactions so it won't record the same sale twice, and your app can handle periods without or with spotty internet access.
As for your error: the timeout probably is a minute or so, which may be too long for this use case anyway. The client will ultimately throw an exception if it doesn't get an HTTP response, but do you want your bar person to wait on the POS for a minute? They are going to call it a POS then.
I recently started using Signal R library in ASP.Net MVC 3 application. I am able to use Signal R to send message to client. But I noticed that if I logged in to the application from another browser, I get following error -
Exception type: InvalidOperationException
Exception message: Unrecognized user identity. The user identity cannot change during an active SignalR connection.
Server stack trace:
at Microsoft.AspNet.SignalR.PersistentConnection.GetConnectionId(HostContext context, String connectionToken)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.Owin.CallHandler.Invoke(IDictionary2 environment)
at Microsoft.AspNet.SignalR.Owin.Handlers.HubDispatcherHandler.Invoke(IDictionary2 environment)
at Microsoft.Owin.Host.SystemWeb.OwinCallContext.Execute()
at Microsoft.Owin.Host.SystemWeb.OwinHttpHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object extraData)
And in some instances, I started getting this error repeatedly. And event log get full in couple of minutes.
I override OnConnect, OnDisconnect functions in my hub class and initiated hub connection from the Java script.
SignalR does not allow a user's Identity to change while maintaining a connection. This is because SignalR's connectionToken acts as an anti-xsrf token.
It appears that your "other" browser must actually be just another browser window. When you log in to the application in another window, it changes your ASP.NET forms authentication cookie (and therefore your Identity) in both browser windows.
Any ongoing SignalR connections will run into the aforementioned InvalidOperationException when they attempt to reconnect after the browser's auth cookie has changed. SignalR may attempt to reconnect quite frequently if the long polling transport is being used. Once the reconnect fails due to the exception, SignalR will repeatedly try to reconnect for about 40 seconds after which SignalR will give up and disconnect.
My app is working well on Azure Websites (not Web role, please exclude web role specific answers !), but sometimes I got the following error in my logs :
System.UnauthorizedAccessException: Access to the path 'C:\DWASFiles\Sites\myAzureWebSiteNameHere\VirtualDirectory0\site\wwwroot' is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileSystemEnumerableIterator`1.CommonInit()
at System.IO.FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler, Boolean checkHost)
at System.IO.Directory.EnumerateFiles(String path)
at System.Web.WebPages.Deployment.WebPagesDeployment.AppRootContainsWebPagesFile(String path)
at System.Web.WebPages.Deployment.PreApplicationStartCode.OnChanged(String key, Object value, CacheItemRemovedReason reason)
at System.Web.Caching.CacheEntry.CallCacheItemRemovedCallback(CacheItemRemovedCallback callback, CacheItemRemovedReason reason)
This happened just before the site is restarted (by Azure, not by me, probably for a maintenance operation on the VM containing the site). So I concluded that it happened during a "shutting down" operation, when the system try to clear the cache.
I'm using the Asp.net cache like this : HttpContext.Current.Cache[myKey] = something and I have not define any specific callback like CacheItemRemovedCallback. The above callstack confirms the error is on a system callback.
It seems to be Azure specific (and perhaps even specific to Azure Websites), because the same website on an on-premise server never had this kind of error.
Do you know how to prevent this error from happening ? Thanks !
I have an ASP.NET HTTP handler hosted on Windows Azure in a "small" compute instance. It handles downloads and uploads of large binary files. Nothing else runs within that web role, and there are 2 instances configured, as per guidelines. When a download is done from a computer with a slow connection and I try to perform several downloads at once to choke the bandwidth on the client side, sometimes I get a ThreadAbortException in the handler, most often during a .Write to the Response.OutputStream (I set Response.BufferOutput = false beforehand). The stack trace is as follows:
System.Threading.ThreadAbortException: Thread was being aborted.
at System.Web.Hosting.UnsafeIISMethods.MgdExplicitFlush(IntPtr context)
at System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush()
at System.Web.HttpResponse.Flush(Boolean finalFlush)
at System.Web.HttpWriter.WriteFromStream(Byte[] data, Int32 offset, Int32 size)
at MyHandler.ProcessGetRequest(HttpContext context)
at MyHandler.ProcessRequest(HttpContext context)
(the Stream.Write call is apparently inlined so it does not show in the stack trace).
Why is the thread being aborted? I am guessing I am hitting some kind of a timeout (possibly a socket write timeout), is aborting the thread a normal way for the ASP.NET runtime to handle it?
Note that it is a single HTTP handler, not an .aspx/.cshtml page or MVC controller, and nowhere in my code am I touching Response.End, Response.Redirect or Server.Transfer.
Whe you upload big files, IIS tries to read request stream and if it blocks for over 5 minutes it would cause IIS to eventually throw ThreadAbortException.
Try playing with this line:
<httpRuntime maxRequestLength="2097150" executionTimeout="3600"/>
Also try these suggestions: http://cutesoft.net/forums/permalink/77440/77438/ShowThread.aspx#77438
I have a .net web application that has a Flex application embedded within a page. This flex application calls a .net webservice. I can trace the execution proccess through the debugger and all looks great until I get the response:
soap:ReceiverSystem.Web.Services.Protocols.SoapException: Server was unable to process request
. ---> System.Xml.XmlException: Root element is missing.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.ThrowWithoutLineInfo(String res)
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlTextReader.Read()
at System.Web.Services.Protocols.SoapServerProtocol.SoapEnvelopeReader.Read()
at System.Xml.XmlReader.MoveToContent()
at System.Web.Services.Protocols.SoapServerProtocol.SoapEnvelopeReader.MoveToContent()
at System.Web.Services.Protocols.SoapServerProtocolHelper.GetRequestElement()
at System.Web.Services.Protocols.Soap12ServerProtocolHelper.RouteRequest()
at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message)
at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest
request, HttpResponse response, Boolean& abortProcessing)
--- End of inner exception stack trace ---
The call from flex looks good, the execution through the webservice is good, but this is the response I capture via wireshark, what is going on here?
I have tried several web methods, from "Hello World" to paramatized methods...all comeback with the same response...
I thought it may have something to do with encoding with the "--->", but I'm unsure how to control what .net renders as the response.
It looks like you might be sending a poorly formed XML document to the service. Can you use Fiddler or something like that to get a copy of the actual call that is going to the web service? That would be a huge help in figured out what the issue is.
I recently used a .NET REST interface which I consumed using a Flex app. I got some strange exceptions as well and my issue was that I forgot to include in xmlns (the namespace) in the root element when sending requests. This is a wild guess but I hope it helps.
Are you using Flex 3? If so, you can set a breakpoint when the webservice is executed and actually step through the Flex framework as it encodes your request. Look in mx.rpc.soap.SoapEncoder and you'll be able to see exactly what is going to be sent over the wire.