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
mystes
May 31, 2006

If it's utf8 you need to decode it first and not just iterate through the bytes

Adbot
ADBOT LOVES YOU

nielsm
Jun 1, 2009



epswing posted:

Control Pictures! Never heard of these, but it looks like what I'm after, thanks.

I guess my concern would be when looping through bytes, how do I know if a given byte is a single byte like 04 that I should replace with the EOT control picture, or part of a multi-byte character that happens to contain an 04 byte? If the text is ASCII encoded, probably nothing to worry about, but if it's e.g. UTF-8 couldn't there by multi-byte chars in there?

If you know the data is a specific encoding, then decode that before trying to display it.
If you don't know what the data is, then don't try to display anything above 0x7F as text since it may be anything. (The rest may also not be ASCII either, in that case, though it's rather likely.)

For UTF-8 in specific, it has an encoding scheme where the byte values 0x00 to 0x7F map directly to ASCII, and the byte values 0x80 to 0xFF have well-defined meanings as either a leading byte or a trailing byte, but never "may be either". Looking at a single standalone byte in UTF-8 encoded text, you can always know if it can be used as-is (it's a low byte), if it's a trailing byte that makes no sense without the lead byte, or if it's a lead byte and then how many more trailing bytes it needs to be decoded into a Unicode codepoint. If you haven't, do read up on how the UTF-8 encoding is designed, it's actually quite elegant.

nielsm fucked around with this message at 21:21 on Oct 12, 2023

brap
Aug 23, 2004

Grimey Drawer
Also you might want to review the built in char and encoding APIs so that you don’t have to write as much of it yourself (e.g. “is control character” APIs).

Kyte
Nov 19, 2013

Never quacked for this
To represent ASCII control codes at least, Unicode actually has a set of glyphs that represent them in picture form.
https://www.fileformat.info/info/unicode/block/control_pictures/images.htm
You could define a mapping and show'em using a font that supports those glyphs (https://www.fileformat.info/info/unicode/char/2400/fontsupport.htm)

nielsm
Jun 1, 2009



I have an API application served via Kestrel. Right now it's on .NET 5 and our team is trying to find time to upgrade to .NET 8, but I don't think that matters for this issue I'm having.

Right now the API is authenticated via Windows Authentication by Negotiate method:
C# code:
    services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
        .AddNegotiate(NegotiateDefaults.AuthenticationScheme, options =>
        {
            options.Events = new NegotiateEvents
            {
                OnAuthenticated = HttpAuthHelper.NegotiateAuthenticated
            };
        });
This works. The HttpAuthHelper.NegotiateAuthenticated delegate pulls some additional data and adds some more specific claims to the Principal in the context, and the rest of the application can access this.

Now, to support a new API consumer that can't handle Negotiate auth, I'm attempting to add HTTP Basic as an alternative. I'd prefer if it never gets advertised in the WWW-Authenticate header in 401 responses, but the main thing is that I need the application to accept either Negotiate or Basic auth, but have clients prefer Negotiate.

For this, I've added the idunno.Authentication.Basic package, and I can make it work:
C# code:
    services.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
        .AddBasic(BasicAuthenticationDefaults.AuthenticationScheme, options =>
        {
            options.Realm = "MyApp";
            //options.SuppressWWWAuthenticateHeader = false;
            options.Events = new BasicAuthenticationEvents
            {
                OnValidateCredentials = HttpAuthHelper.BasicValidateCredentials
            };
        });
When I change the service configuration to add Basic instead of Negotiate, it works just fine. It calls my HttpAuthHelper.BasicValidateCredentials delegate, which receives the credentials sent, validates them, and adds the necessary claims.

However, getting the two to work at the same time has me stumped.

I've tried adding both one after each other, with two separate services.AddAuthentication calls. In that case, the last one added "wins", and the other is never initialized at all, the "options" delegate is not even called for it.

I've tried a single services.AddAuthentication(...).AddBasic(...).AddNegotiate(...), i.e. adding authentication once and then adding both methods. Then the method named as default in the AddAuthentication call wins, and the other is never initialized.

I've tried a few different setups with more complex options for AddAuthentication:
C# code:
    services.AddAuthentication(options =>
    {
        options.DefaultScheme = NegotiateDefaults.AuthenticationScheme;
        options.DefaultAuthenticateScheme = BasicAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = NegotiateDefaults.AuthenticationScheme;
    })
    .AddNegotiate(...)
    .AddBasic(...)
Then I can authenticate via Basic if I send then Authorization header in the initial request, and if I don't then the application responds with a WWW-Authenticate: Negotiate header. But for some reason, then a web browser trying to access the API (via an Angular application) never completes the Negotiate and just gets 401. (Both the Network tab in the browser's dev tools and a direct call with cURL -v shows that the application is sending the header.)
This seems to be the closest I've gotten to make it work. But I don't know why the browser fails to complete the Negotiate auth or where to look for any debugging related to that.

I've tried adding ForwardDefault, ForwardChallenge, ForwardForbid and more properties to the options of each of the two schemes, and it either does nothing, or gives me a variation of the above.
I've tried with and without the SuppressWWAuthenticate header in the options for Basic, it doesn't get me closer.

I've attempted to call options.AddScheme in the delegate to AddAuthentication, but I can't do it properly since while the NegotiateHandler class is public, the BasicAuthenticationHandler class is internal and not accessible in my application code... I don't know if it ought to be accessible to application code.


Do anyone know what the proper way to go about this is, or have ideas for other things to try?

Kyte
Nov 19, 2013

Never quacked for this
https://github.com/dotnet/aspnetcore/issues/27025
https://stackoverflow.com/questions/73214521/asp-net-core-6-add-multiple-authentication-schemes-with-multiple-authorization

Apparently if you set a default scheme it will always run, so I imagine one of the two is running when you're trying to use the other and 401'ing since it's missing the required information.
Try not actually setting a default (and unsetting defaults if they get added) and then make your policies allow either scheme.

epswing
Nov 4, 2003

Soiled Meat

nielsm posted:

Do anyone know what the proper way to go about this is, or have ideas for other things to try?

I don't have the answer to your question, but I recognize how deeply """SOFTWARE DEVELOPMENT""" this is and empathize with your efforts to wrangle what appear to be complex opposing forces. :sympathy: :smithicide:

nielsm
Jun 1, 2009



Maybe I won't need to solve it either way... someone else involved argued that we should find some way to get that one consumer to do Negotiate auth properly, rather than change the API, which I quite agree is preferable.



I may look at this tomorrow.

Kyte
Nov 19, 2013

Never quacked for this

nielsm posted:

Maybe I won't need to solve it either way... someone else involved argued that we should find some way to get that one consumer to do Negotiate auth properly, rather than change the API, which I quite agree is preferable.

I may look at this tomorrow.
By the way, you already mentioned the Forward options, but not sure if you tried AuthenticationBuilder.AddPolicyScheme.
This doc has some further information addressing your scenario.

epswing
Nov 4, 2003

Soiled Meat
Tell me about your favourite HTML -> PDF converter! I haven't had to do this in a while, notably since the shift from .NET Framework to .NET Core. Has the dotnetcore community gravitated towards a particularly good solution/library? Or is using a 3rd party service the way to go these days?

Edit: I should mention the environment here is an .NET 6 ASP.NET site running as a Web App in Azure. I'm familiar with tools like wkhtmltopdf.exe but I don't think that'd work in this case (there's no filesystem/OS to play with). The html will come from some url, and the resulting pdf will be stored in some cloud storage bucket.

epswing fucked around with this message at 15:27 on Dec 11, 2023

Just-In-Timeberlake
Aug 18, 2003

epswing posted:

Tell me about your favourite HTML -> PDF converter! I haven't had to do this in a while, notably since the shift from .NET Framework to .NET Core. Has the dotnetcore community gravitated towards a particularly good solution/library? Or is using a 3rd party service the way to go these days?

Edit: I should mention the environment here is an .NET 6 ASP.NET site running as a Web App in Azure. I'm familiar with tools like wkhtmltopdf.exe but I don't think that'd work in this case (there's no filesystem/OS to play with). The html will come from some url, and the resulting pdf will be stored in some cloud storage bucket.

We use https://www.api2pdf.com/, cheap, fast, and accurately renders the HTML => PDF, and the generated PDFs get stored in an S3 bucket.

They have SDKs for python, node, php, c# and java and several different rendering engines to choose from:

https://app.swaggerhub.com/apis-docs/api2pdf/api2pdf/2.0.0

Polio Vax Scene
Apr 5, 2009



we have a company license for devexpress so we just feed it into that steamroller

brap
Aug 23, 2004

Grimey Drawer
Azure app service has an underlying disk which you can access through normal file APIs. It’s possible that certain parts of it are transient and get wiped when instances shut down or something. I don’t see why just spawning a subprocess to convert to PDF, then reading the result off disk wouldn’t work.

Surprise T Rex
Apr 9, 2008

Dinosaur Gum
What's the state of the art for creating PDFs in C# code now? Ideally one I can run from a serverless Azure Function or AWS Lambda. At work we do some of this using rendering Razor templates to HTML and feeding it to Puppeteer(?) to basically fake a print-to-PDF, but that requires us to run it as a docker container so we can bundle a headless Chrome with it and that seems like more effort than is necessary.

QuestPDF seems good but new and I'm not sure if I'm just being blinded by it looking semi-modern.

Mega Comrade
Apr 22, 2004

Listen buddy, we all got problems!
We switched to IronPdf last year and it's been nothing but trouble.

Constant bugs and time out issues.
They push out breaking changes with no documentation.
Their verbose logging is trash and spits out stuff they don't know what it means.

Avoid.

Sab669
Sep 24, 2009

I've been using iText at work for the last 2 years and it seems... fine? I use it to loop over some model object and print out HTML tables and then turn that to PDF.

I mostly don't have strong opinions of it, except for on a new project we've found that when a user pastes an image into these rich text editors on the front end, then try to use that field's value the image doesn't get scaled to the size of the page.

Turns out the way we were handling this ceased working when we upgraded to a newer version of that library :v: Spent all day yesterday scratching my head over it but finally got it working again.

Just-In-Timeberlake
Aug 18, 2003

Surprise T Rex posted:

What's the state of the art for creating PDFs in C# code now? Ideally one I can run from a serverless Azure Function or AWS Lambda. At work we do some of this using rendering Razor templates to HTML and feeding it to Puppeteer(?) to basically fake a print-to-PDF, but that requires us to run it as a docker container so we can bundle a headless Chrome with it and that seems like more effort than is necessary.

QuestPDF seems good but new and I'm not sure if I'm just being blinded by it looking semi-modern.

I recommended api2pdf a few posts up, I still recommend it. It costs next to nothing (we generated ~50k pdfs in December, cost ~$30), multiple converters and .pdf utilities to choose from, and I don't have to maintain poo poo.

https://app.swaggerhub.com/apis-docs/api2pdf/api2pdf/2.0.0

I found the Wkhtmltopdf converter to do the best job in accurately converting HTML to a .pdf

Just-In-Timeberlake fucked around with this message at 14:08 on Jan 9, 2024

mystes
May 31, 2006

Surprise T Rex posted:

What's the state of the art for creating PDFs in C# code now? Ideally one I can run from a serverless Azure Function or AWS Lambda. At work we do some of this using rendering Razor templates to HTML and feeding it to Puppeteer(?) to basically fake a print-to-PDF, but that requires us to run it as a docker container so we can bundle a headless Chrome with it and that seems like more effort than is necessary.

QuestPDF seems good but new and I'm not sure if I'm just being blinded by it looking semi-modern.
Questpdf looks nice but iirc it still can't do font subsetting so it sucks unless you just need to support english (the files will be huge)

If you can run an external program written in Python I think weasyprint is pretty good as an HTML to PDF converter (as long as you're writing the HTML specifically for it). It produces very good results and doesn't use a headless browser. I'd imagine you can find some way to bundle it so you don't actually need to use containers but that's still more of a pain than an actual .net library (I'm surprised they don't provide a standalone windows .exe version)

mystes fucked around with this message at 14:40 on Jan 9, 2024

epswing
Nov 4, 2003

Soiled Meat

Just-In-Timeberlake posted:

I recommended api2pdf a few posts up, I still recommend it. It costs next to nothing (we generated ~50k pdfs in December, cost ~$30), multiple converters and .pdf utilities to choose from, and I don't have to maintain poo poo.

https://app.swaggerhub.com/apis-docs/api2pdf/api2pdf/2.0.0

I found the Wkhtmltopdf converter to do the best job in accurately converting HTML to a .pdf

For what it's worth, I started using api2pdf, and it seems to Just Work. I don't like that it's an external dependency and would rather this processing happen on my servers, but to get something up and running quickly it's a no brainer. The headless Chrome converter came closest to the source input so that's what I ended up using.

Thanks for the recommendation.

Edit: Some thoughts and feelings: At first glance it seems like a hack to first generate html and then use that to generate the PDF you want. But the alternative is so much worse, to build the PDF using code sucks so bad, the procedural nature of writing new TableRow(new TableCell(new Paragraph(new Run("hello"), new Options { MarginTop: 10 }))))))))))))))) in C# is just awful. Building anything visual with a declarative language is comparatively blissful.

epswing fucked around with this message at 15:28 on Jan 9, 2024

mortarr
Apr 28, 2005

frozen meat at high speed

Surprise T Rex posted:

What's the state of the art for creating PDFs in C# code now? Ideally one I can run from a serverless Azure Function or AWS Lambda. At work we do some of this using rendering Razor templates to HTML and feeding it to Puppeteer(?) to basically fake a print-to-PDF, but that requires us to run it as a docker container so we can bundle a headless Chrome with it and that seems like more effort than is necessary.

QuestPDF seems good but new and I'm not sure if I'm just being blinded by it looking semi-modern.

Three or four years ago, I built an on-prem latex to PDF pipeline controlled by a c# app, because I couldn't get management approval for paid-for pdf libraries. The document included dynamic/user-selected collections of datasets from lists to tables with multiple levels of grouping, images, as well as hyperlinked contents and indexes.

I found while using the c# libs of the time that some of the more complex tables were glitchy, and did not render correctly. Swapping to latex was a pain, and it was completely new to me, but the debug experience was a lot easier and the final output pdf was a lot cleaner and smaller than I was able to generate otherwise.

Not entirely sure I'd recommend the latex route unless your document is complicated, and the state of the art may have moved on now - particularly with paid-for services, but latex might be something to bear in mind.

Canine Blues Arooo
Jan 7, 2008

when you think about it...i'm the first girl you ever spent the night with

Grimey Drawer

Surprise T Rex posted:

What's the state of the art for creating PDFs in C# code now? Ideally one I can run from a serverless Azure Function or AWS Lambda. At work we do some of this using rendering Razor templates to HTML and feeding it to Puppeteer(?) to basically fake a print-to-PDF, but that requires us to run it as a docker container so we can bundle a headless Chrome with it and that seems like more effort than is necessary.

QuestPDF seems good but new and I'm not sure if I'm just being blinded by it looking semi-modern.

If your document doesn't need complex elements, I'd just do it in PDFSharp/MigraDoc. I've used it in the past and it's been easy enough to use if a bit verbose. If you aren't actually interested in constructing a PDF, but just printing one, I guess you can use a service but then prepare for all the poo poo that comes with it.

You don't need this mess of services and containers and all this poo poo just to run a browser so you can 'fake' print a PDF. Like, at some level of document complexity, that becomes an attractive solution, but holy poo poo this pipeline can begin and end at 'project code'.

Canine Blues Arooo fucked around with this message at 03:56 on Jan 11, 2024

NiceAaron
Oct 19, 2003

Devote your hearts to the cause~

I won't claim to have extensive experience with every way to generate PDFs from C#, but all the ones I've used sucked in some way compared to just using headless Chrome. Being able to preview and debug the HTML in a browser, and being confident that the resulting PDF will look the same when generated by your app, can be a huge advantage, depending on your needs.

Maybe setting it up is more effort than necessary, or maybe it's exactly as much effort as is necessary.

edit: And if your boss / client gives you fucky requirements like "I want this report to always fit on a single page, can you automatically shrink the font a bit if there's too much text?" you can write some Javascript code that does it.

NiceAaron fucked around with this message at 03:45 on Jan 11, 2024

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug
PDFs and containers don't mix. I've had some bad surprises.

Alan G
Dec 27, 2003
Probably not what is being looked for, but I have used Ibex for years https://www.xmlpdf.com/. That old app is still on Framework so can't speak for the newer .Net Core/.Net versions of the lib though. You use XSLT to transform XML into XSL-FO then onto PDF (or html/rtf/whatever). A bunch of times I hit an issue, usually with localisation, or when they rewrote their own SVG engine at a major version jump, I'd submit a bug with a sample. Come in the next day to an email to download the new version with a fix. Never had an external library owner be so responsive.

Now working on a Java app where we use apache fop to transform json using thymeleaf templates which is definitely a lot simpler. From a quick search it looks like there's a dead attempt to convert that to .net too, which is interesting, wonder how much effort is involved in that kind of thing https://www.nuget.org/packages/crispin.fop

Hughmoris
Apr 21, 2007
Let's go to the abyss!
A novice question from a hobbyist:

Is it painful to call a F# library from Winforms or WPF? Can I:
  • write a simple parsing library in F#. Compile it.
  • Create a Winforms application in C#. Have an input field, click a button that calls the F# library to parse the input, then output the result to a new field.

At the 'Hello World' level so far, I enjoy writing in F#. But I want to create simple GUIs as well. Is combining both a bad path to take?

mystes
May 31, 2006

Hughmoris posted:

A novice question from a hobbyist:

Is it painful to call a F# library from Winforms or WPF? Can I:
  • write a simple parsing library in F#. Compile it.
  • Create a Winforms application in C#. Have an input field, click a button that calls the F# library to parse the input, then output the result to a new field.

At the 'Hello World' level so far, I enjoy writing in F#. But I want to create simple GUIs as well. Is combining both a bad path to take?
If you want to call f# code from c#, it needs to be a separate project, but you can just have a separate f# project and reference it in your c# project.

However, if you want to use f# I would suggest trying Avalonia.FuncUI* or making a webapp instead of using winforms/wpf from c#.

*: You can also use https://github.com/JordanMarr/ReactiveElmish.Avalonia, or if you really want to use WPF rather than avalonia you could use https://github.com/elmish/Elmish.WPF to use it from f# too, I guess

mystes fucked around with this message at 22:32 on Jan 15, 2024

NihilCredo
Jun 6, 2011

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

Hughmoris posted:

A novice question from a hobbyist:

Yes, what you want to do is both trivial and common. You can reference a F# library project in the same way as a C# library project.

The only potential pain point, but I hesitate to even call it that, is that if the F# function you want to call uses F#-idiomatic data structures (linked lists, unions / option types), they will look a little weird from the C# code that calls them, with weird names like FSharpOption etc. - but they will work just fine, you can both create and consume them from C#.

As mystes points out, writing the UI in F# is also an option. However, except for Elmish.WPF, the other options don't come with a nice visual designer.

NihilCredo fucked around with this message at 22:36 on Jan 15, 2024

Hughmoris
Apr 21, 2007
Let's go to the abyss!
I got a proof of concept working in the console. I'll take a look at those F# GUI frameworks. Thanks!

Surprise T Rex
Apr 9, 2008

Dinosaur Gum
Started setting up a .Net 8 Azure Function to handle my PDF generation stuff as discussed earlier in the thread... and uh, the Azure Functions Deployment Centre option to auto-generate a CI Github Actions workflow doesn't seem to work? It creates the file and sets up the action on my repo, but it doesn't succeed at actually deploying.

It created a workflow file that had a bunch of problems: it had no "contents: read" permission set up so the action had no permission to do anything useful, it seemed to have a step that was trying to login to the az cli using an Microsoft Entra ID client id/secret and that's confusing as hell, so I've replaced that with using the Publish Profile downloaded from the Azure Portal instead, but then the Function resource I created didn't have a Storage Account associated with it (which I didn't think was even possible?), and after creating one and setting the AzureWebJobsStorage app setting to the connection string for it, it's still failing to actually do the zip deploy.

Am I missing something getting this to work? I can't tell if it's me or Azure. Is it just not possible on a free trial Azure account? Maybe it doesn't work with private repos?

Finster Dexter
Oct 20, 2014

Beyond is Finster's mad vision of Earth transformed.
Quick question. Rider has a feature that does autocomplete from nuget.org for PackageReference versions when editing csproj files. Is there an extension for VS that provides the same thing?

epswing
Nov 4, 2003

Soiled Meat
I'm down the rabbit hole on Culture and currency in .NET, I've got a bit of a legacy app that was migrated to .NET 6 that has lots of properties containing currency amounts that, eventually, need to be visualized (printed, exported, displayed in WPF, displayed in ASP). If I do val.ToString("C") and the culture is en-US I get e.g. "$4.95" as expected. This is fine when displaying reports in ASP, the server is set to a given culture by setting CultureInfo.DefaultThreadCurrentCulture and CultureInfo.DefaultThreadCurrentUICulture, so whichever page I'm viewing, the server dictates the culture and I get the right currency symbol.

However, the WPF app, which pulls data down from the ASP server above), is running on the user's computer, whose OS is set to e.g. en-GB, and displaying the same val.ToString("C") results in £4.95, which is wrong.

Should each currency properties each come with a companion "CurrencySymbol" property, kind of like units accompanying measurements (grams, lbs, etc)? The software doesn't do multi-currency, so ideally there should be one place to set The Currency Symbol on startup, but setting CultureInfo.DefaultThreadCurrentCulture and CultureInfo.DefaultThreadCurrentUICulture (or Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture) doesn't seem to accomplish this.

I'm reading a lot but still lost, any advice?

brap
Aug 23, 2004

Grimey Drawer
Is the app localized in any other way? e.g. using different localized text depending on the user's culture.

I'm uncertain why setting CurrentCulture to US is not formatting currency in the expected fashion in WPF. It might be a good idea to do a little digging into how localization works in WPF. Perhaps something on the framework level is controlling the UI thread's culture, for example.

However, it might be reasonable to explicitly pass a CultureInfo which formats the currency in the way you want to these ToString calls. Maybe there isn't a need to set "The Currency Symbol To Use" on startup, but rather the culture to use when formatting currency.

epswing
Nov 4, 2003

Soiled Meat

brap posted:

Is the app localized in any other way? e.g. using different localized text depending on the user's culture.

I'm uncertain why setting CurrentCulture to US is not formatting currency in the expected fashion in WPF. It might be a good idea to do a little digging into how localization works in WPF. Perhaps something on the framework level is controlling the UI thread's culture, for example.

The app is localized in some other ways, e.g. displaying the date/time the way the user's used to seeing it. But the difference between "8:05 PM" vs "8:05 p.m." vs "20:05" is purely visual, an annoyance at worst, however the difference between $1 and €1 is bad for business.

Seems strange to me to set properties "on the current thread", as if I'm supposed to keep track of what's happening to CurrentCulture on each thread. E.g. say I spin off a background thread to generate a report and write it to disk, would/could that have a different culture than the rest of the application?

brap posted:

However, it might be reasonable to explicitly pass a CultureInfo which formats the currency in the way you want to these ToString calls. Maybe there isn't a need to set "The Currency Symbol To Use" on startup, but rather the culture to use when formatting currency.

Sometimes the currency symbol is displayed alone, e.g. in a list header like "Price ($)" to indicate "price in dollars", so I still need a way to display just the currency symbol. I suppose storing some global Culture variable would work (and might be necessary?), but is that really how to handle this rather than setting/using CultureInfo.CurrentCulture, is my main question at this point.

bobthenameless
Jun 20, 2005

not sure about the WPF specifics, but it sounds like there you might want to set the values there with https://learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/system-globalization-cultureinfo-invariantculture like
pre:
val.ToString("C", CultureInfo.InvariantCulture)
which I think would do what youre asking? i understood it as the currency should match whatever the server's culture is, so in your example the en-GB WPF client should still show $ and not pounds?

e: also, i think the culture per thread bit is a windows thing for threads in general and not just a dotnet thing
e2: actually i guess this probably doesnt do what you want and just returns the number as is. cultureinfo.numberformat.CurrencySymbol does keep the culture's currency symbol if thats helpful, maybe on the web side have it return a header or field with the culture string if possible

bobthenameless fucked around with this message at 06:04 on Feb 21, 2024

Kyte
Nov 19, 2013

Never quacked for this
ToString does not perform currency conversion. If the amounts are in USD then show it in USD either by hardcoding the symbol or always passing the en-US culture to ToString.

Asking the user for their currency symbol preference is the wrong question to ask. If you need to ask, ask the user for their currency conversion preference, and then include explicit logic to convert those USD via whatever exchange rate you deem appropriate (this question may be much harder than you think). And ideally you still show the original amount.

E: If worst-case you find a place where you can't pass a culture specifier, you can, during startup, create a new custom culture based on the current culture, change the currency format specifier and set the new culture as current. IIRC threads inherit the current culture from the thread that spawns from so if it's done on startup it flows fine. I've done this in ASP.net applications because wrangling that stuff to work correctly for non-English locales is a nightmare.

E2: Apparently WPF just uses en-US by default??? Unless it was fixed in later releases.

Kyte fucked around with this message at 22:44 on Feb 21, 2024

redleader
Aug 18, 2005

Engage according to operational parameters

americans when they learn there are other countries in the world

insta
Jan 28, 2009

epswing posted:

The app is localized in some other ways, e.g. displaying the date/time the way the user's used to seeing it. But the difference between "8:05 PM" vs "8:05 p.m." vs "20:05" is purely visual, an annoyance at worst, however the difference between $1 and €1 is bad for business.

Seems strange to me to set properties "on the current thread", as if I'm supposed to keep track of what's happening to CurrentCulture on each thread. E.g. say I spin off a background thread to generate a report and write it to disk, would/could that have a different culture than the rest of the application?

Sometimes the currency symbol is displayed alone, e.g. in a list header like "Price ($)" to indicate "price in dollars", so I still need a way to display just the currency symbol. I suppose storing some global Culture variable would work (and might be necessary?), but is that really how to handle this rather than setting/using CultureInfo.CurrentCulture, is my main question at this point.

Are you expecting localization to perform currency exchange calculations?

epswing
Nov 4, 2003

Soiled Meat

insta posted:

Are you expecting localization to perform currency exchange calculations?

Of course not, that’s silly.

I want the culture of the client (a WPF app) to be the same as the culture of the server (an ASP app) instead of the default/OS culture of the PC running the client.

insta
Jan 28, 2009

epswing posted:

Of course not, that’s silly.

I want the culture of the client (a WPF app) to be the same as the culture of the server (an ASP app) instead of the default/OS culture of the PC running the client.

no i think I'm going to still assume you wanted a static library to do accurate currency conversions years later.

that's silly. what you want is silly.

Adbot
ADBOT LOVES YOU

ThePeavstenator
Dec 18, 2012

:burger::burger::burger::burger::burger:

Establish the Buns

:burger::burger::burger::burger::burger:
This is 100% an XY problem. Setting the entire UI thread sounds like a bad plan - what happens if you set the UI thread to have a culture for "zh-CN" when the currency in question is the Yuan, and then the entire UI ends up translated into Chinese on a UK/US user's computer without Chinese language support installed?

This is a pretty non-negotiable software design pattern IMO - Money really needs to be represented as a (Currency, Amount) tuple and the issues you're running into (someone in Great Britain needs to be shown US dollar amounts in the UI) illustrate why, here's a NuGet package if you want a pre-baked implementation of a Money data structure - https://www.nuget.org/packages/nmoneys

If you're not going to update your legacy application to follow this pattern you can always set the UI thread to a custom culture where everything is the same as the user's default UI culture, but you set the currency symbol yourself, but that's not foolproof either - different cultures have different ways of expressing things like negative currency amounts, and the second this is no longer true:

epswing posted:

The software doesn't do multi-currency

...you'll be forced to make the conversion and wish you had done it in the first place.

e:

You don't necessarily have to use that NuGet package to be clear. If you know what the currency is in the UI (as in, the legacy code already has some way of identifying the currency that just isn't used when converting to a string), you can implement a GetCurrencyCulture() method that accepts the currency and then returns the appropriate .NET culture for the currency, and then you can provide that culture as a parameter in your string.Format call - https://learn.microsoft.com/en-us/d...(system-string)

ThePeavstenator fucked around with this message at 02:28 on Feb 26, 2024

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