Skip to content

Troubleshooting — Integrations

Problems with the services the application depends on: AWS S3, SMTP e-mail, PDF rendering, SignalR, and two settings that act like integrations — the attendance IP allow-list and the global exchange rate. Background: External Services.

Uploads and downloads (S3)

Every document upload and download goes through S3ServiceHandler, which first finds the bucket and folder for the feature:

var system = _settings.StorageConfigs.Systems.First(x => x.Functionality == functionality);
Symptom Cause Fix
InvalidOperationException: Sequence contains no matching element StorageConfigs:Systems has no entry for this feature's Functionality. Add it. All 19 values need an entry — see Configuration.
The same error on every asset-disposal upload NKODestruction is missing from the example configuration, so every configuration built from it lacks it (R4-1). Add the NKODestruction entry.
AmazonS3Exception — InvalidAccessKeyId, SignatureDoesNotMatch or AccessDenied Wrong clientId / clientSecret, or the IAM user lacks rights on that bucket. The app still starts; it fails only on first use. Fix the credentials, or the bucket policy.
AmazonS3Exception — the bucket is in a different region StorageConfigs:region does not match the bucket. Use the bucket's region.
Upload of a large file fails before reaching the app No upload limit is configured anywhere in the code, so the host default of 30,000,000 bytes (about 28.6 MB) applies. IIS rejects larger requests itself. Larger files need a hosting change (maxAllowedContentLength in the site's web.config), and possibly an application change.

No e-mail arrives

E-mail fails silently: both send methods in EmailManager wrap the SMTP call in an empty catch (R1-6), so there is no error and no log. Work through these in order.

# Check Why
1 SELECT SettingValue FROM CommonSetting WHERE SettingId = 6 returns True Both send methods return without sending unless this row exists and parses as true. On a new database it does not exist (R5-5).
2 The recipient is an employee with login enabled Approval notifications (the SendEmail(subject, body, link, to) path) are sent only if an AppUser has that exact Email and its login is enabled. Anyone else is skipped.
3 The server can reach smtp.office365.com on 587 The host and port are hard-coded in EmailManager.
4 The sending mailbox's password is still valid It is compiled into SiteSettings.cs (R1-9). A password change needs a rebuild and redeploy, not a configuration change.
5 The mailbox may send through authenticated SMTP Microsoft 365 can disable SMTP AUTH per mailbox or tenant. If it is off, every send fails — silently, here.

To see the actual SMTP error, run the application locally with a debugger and break on thrown exceptions: the exception is raised, then swallowed.

Links in e-mails point to the wrong site

Notification links are built from SysUrl plus the page path, and several URLs are compiled into SiteSettings.cs. A build made for one environment carries that environment's URLs (R4-4). Check SysUrl first; if it is right, the build was made for another environment.

PDF export

PDFs are rendered by Rotativa, which runs wkhtmltopdf.exe from wwwroot\Rotativa\ as a separate process.

Symptom Cause Fix
Every PDF export fails on a new install wwwroot\Rotativa\ is not in the repository and no binary ships (R5-3). Place the wkhtmltopdf binaries matching Rotativa.AspNetCore 1.2.0 there.
Every PDF export fails right after a publish The IISProfile publish profile deletes files that are not in the package, including the binary (R4-3). Put the binary back, and publish with extra files kept.
Fails with an access-denied error The app-pool identity cannot execute the binary. Grant Read & execute on wwwroot\Rotativa\.
Jobs and Advance PDFs have no header or footer, or time out Those exports make wkhtmltopdf fetch the header and footer from the site's own public HTTPS address. The server cannot reach itself, or wkhtmltopdf rejects the certificate. Allow the server to resolve and connect to its own host name ("hairpin"), and use a certificate it trusts — see Server Requirements.

Real-time notifications

The top-bar badge and several exports use the SignalR hub at /hub.

Symptom Cause
Badges update only after a refresh The browser cannot keep a connection to /hub. Check the browser console. Without the IIS WebSocket Protocol feature SignalR falls back to long polling, which still works but is slower.
Works for some users, not others More than one worker process. SignalR has no backplane, so a message reaches only users on the same process (R4-5).
Nothing works, and links are broken too The site is installed as an IIS sub-application. The client connects to the root-absolute /hub.
A warehouse or login-history export shows progress, then never offers the file These exports run in the background — warehouse ones in Hangfire, login history in Quartz — and deliver the download link over SignalR. If the connection dropped, or the job ran on another process, the link never arrives. The file itself is written under C:\upload\…; check that folder exists (see Deployment).

Attendance check-in rejected

Employees without Allow remote attendance can check in or out only from an allowed IP address.

The allowed list is CommonSetting row ips: a comma-separated list, compared as exact strings. The messages are "You can't checkin/checkout on this IP address." on the home page and "Not Authorized ChechIn Or CheckOut For IP : x" on the attendance screen. The second one shows the address the server saw, so use it to diagnose.

Cause Check
The office's public address changed Compare the address in the message with the list.
Spaces in the list The value is split on , without trimming, so 1.2.3.4, 5.6.7.8 never matches the second address.
A range was entered Ranges and CIDR notation are not supported; list each address.
The site is behind a reverse proxy or load balancer The address comes from Connection.RemoteIpAddress, and no forwarded-headers middleware is configured, so every user appears as the proxy's address.
IPv6 A client reaching the server over IPv6 is compared by its IPv6 address.
Home page only: "Please upload your e-signature to activate check in/out." The home-page check-in also requires an approved e-signature.

To exempt an employee, set Allow remote attendance on their record (/HumanResource/EditEmp).

Exchange rates

There is no exchange-rate feed. The fixer.io client in the code is never called (R7-17), and the global rate in ExchangeRates has no write path in the application (R7-1).

That rate converts TL and EUR purchase requests to USD, and the USD value decides which segregation-of-duties sign-offs a PR needs ($1 000, $5 000, $10 000, $100 000 thresholds). If no row is enabled, every TL/EUR PR is valued at $0 and skips all of them.

SELECT ExchangeRateId, Year, TRYRate, EURRate, IsEnable FROM ExchangeRates WHERE IsEnable = 1;
  • The rates are USD per one unit of the currency, because the code computes usd = amount × rate. TRYRate is therefore a small number (USD per 1 TL), not TL per USD.
  • Keep exactly one enabled row. The lookup takes the first enabled row with no ordering, so with several it is undefined which one is used.
  • Payroll allocation and purchase-order lines use per-donor rates (DonorExchangeRate, under Administration → Donors), not this table. If an allocation's recorded EUR rate equals its USD rate, that is R7-2: the audit column copies the wrong rate, although the EUR amount itself is computed correctly.