Data Annotation Phone Number Conversion - c#

I want to gracefully convert phone number input from my users into a specific phone number format.
I would like convert this with a dataAnnotation, Just as
[dataType(dataType.Date)] displays a dateTime as a string
Ie:
0205938472 into +61205938472
02 0593 8472 into +61205938472
0593 8472 into +61205938472 (I will assume the area code from where
they live or if its a mobile)
02-0593-8472 into +61205938472
Etc, I also want to convert the other direction:
+61205938472 into 02 0593 8472 (Or whatever format i choose)
I want to do this to promote readability for the user but retain a strict data type in the database.
Questions
Is using a dataAnnotation in this manner considered bad practice?
How would I actually write the dataAnnotation( /However you would do it)?
(please include some code)
Edit: to clarify, i do not want someone to write the extension for me, I would just like an example of key pieces of code and implementation.
Please Note
These are Australia, New Zealand and internationally formatted
numbers being stored as internationally formatted numbers.
And International Formatted numbers being converted to Australia, New Zealand or internationally formatted depending on the user's location (which i can determine)

Depending on the UI you're using, you might be able to do this using a:
ASP.NET: Custom binding code (see example)
ASP.NET MVC: ModelBinder
WPF: CustomBinder
Windows Forms: Custom Converters/Editors
As parsing and formatting usually happens in the UI layer, I doubt you will find a solution that works at the data/model layer and which will work universally or which can do more than just validation.
In the data annotations namespace, there is a DataType.PhoneNumber which you can attach to your properties. Though you, yourself, remain responsible to do the parsing and the formatting using the appropriate display technology.

Data annotations and datatype are used for validation, not for converting values. The datatype is mostly used so that the validation knows where to start guessing.
2. That is asking too much for someone to code an extension like that, especially without showing any effort.

You can use DataTypeAttribute like so:
[DataType(DataType.PhoneNumber)]
public string PhoneNumber{get; set;}

Related

General number formatting (#,00) in mvc asp.net and switching between formats

My main problem is that i need to be able to have asp.mvc accept the Danish number format (meaning a dot every thousand and a comma seperator). Since i am working on a larger system, I need a more in-depth solution.
The formating problem includes the fact that I need to beable to solve the errorhandling aswell, which does not accept the 0,00 as a number. best case, the solution still maintains the possibility to calculate with the numbers without having to format them each time.
As another point, I need to beable to switch between the English format, meaning (0.00) and the Danish (0,00).
TL;DR
Solve the problem of using a diffrent formatting in mvc asp.net from (en 0.00) to (da 0,00), including errorhandling, still allowing for calculations in jquery or javascript, and the posibility to switch back to the english format (0.00).
What would be the best way to go about this?
Edit: Solved most of it!
To get the View (Jquery validate) to accept comma as a seperator I've inserted "One regexp" from this: http://mfranc.com/javascript/jquery-valdiator-modyfing-decimal-separator/
Adding the custom model binding, provided by #chrispratt solved the problem of the controller receiving the number in the right format.
On top of this I've added code to modify any number entered into an input field into the right format.
Also all numbers and their display formats are checked before being shown. (since some doubles display without ,00)
I think that should be it, now all that remains is to devise some method of switching between languages and formats, which I should beable to manage.
Thanks for the help!
Any help is apprichiated!
Thanks in advance!

Forcing decimal point instead of comma

I am having a problem with dataformatting in SQL, C#, Razor and HTML5
In my database is a field which has to represent a currency, however the datatype is decimal(18,2), every value saved to the database is saved with an decimal point.
In my DTO the type is also decimal.
However when i give the EditorFor the type number, the field is null when it loads the page.
When i give the EditorFor the type money, the field is filled with the correct value, however it places an comma instead of an decimal point which let it kick in an validation error when the form submits. I have to manually change the comma to an decimal point for it to correctly submit.
I have allready tried setting the type of the EditorFor to number and setting the step property but then it still keeps my input empty.
This is the record in the database
This is the record in my view
this is the generated html markup
UPDATE:
I changed the globalization settings to en-US, this fixed the comma to decimal point question but screws up my date annotation, so down the line i'd like the data annotation to be nl-NL (or similar) and the number format to be en-US (or similar)
Note: it is not allowed to make any changes to the database regarding data-types.
Note: debugging is done on Google Chrome and Microsoft Edge
If in your model or ViewModel you can use this with data annotations:
[DisplayFormat(DataFormatString = "{0:$###,###}")]
If in your controller you can use:
string.Format("{0:$###,###}", yourContext.yourDataFieldname);
Things like formatting and parsing are culture-sensitive.
For the server i.e. ASP.NET, that is the culture of the current thread/execution context.
Thread.CurrentCulture Property
Thread.CurrentUICulture Property
For the client/browser, it sets the Accept-Language header depending on the browser configuration and/or the OS/regional settings. You could allow people to click a flag to change language by storing an override somewhere (session state, cookies, query string ?ln=en-us, route `http://localhost/nl-nl/home/index, ...)
It's probably best to honour Accept-Language first, then if needed allow the culture that would be implied be overridden by user action through one of the other methods.
Essentially, on the server, you need to set the culture and/or UI culture of the current execution context (which not necessarily is as coarse as the thread, since there is async/await and multiple requests might serve on the same thread, but that will be taken care of through the concept of the execution context automatically for you)
See
HOW TO: Set Current Culture Programmatically in an ASP.NET Application
Set Culture in an ASP.Net MVC app
List of HTTP header fields
Content-Language and Accept-Language
The last thing that might be needed or not - I don't quite know - is perhaps to add something to the validation attributes on the page if needed. But you might get lucky and find out that MVC does this automatically.
Note that you can/have to change the Windows Regional Settings to have IE/Edge send a different language list.
Note that the list might actually contain a list of languages and you might need to match those with the languages of resources in your app (if applicable), perhaps picking another than the first one mentioned if say the client asks for Chinese, Dutch and US English (in that order), if in this case you want to serve using Dutch locale rather than culture nutral / invariant culture / by convention US English.
Try to put this in your asp.net web.config file:
<globalization
culture="en-US"
uiCulture="en-US"
/>

formatting dates incorrectly, trying to understand the reason

sorry if this question is a little ... strange, but I am a little lost to what is happening and how to control it. What I need to better understand is the following:
I have an ASP MVC application that works with Linq-To-SQL and an MSSQL server. The application is an inside (office only) website, and I am mentioning that so it wont sound that strange when I say that we wanted to ignore browser language, culture, date, whatever... settings and always display the date in the format "dd/MM/yyyy". Always.
So, now that I am testing a specific form in the website I encounter something very, very strange.
The first strange thing is that the date is not displayed on the screen correctly. Let me elaborate, I have a simple view that gets some data, read from the database, inside a model. So, as I fought for sometime with teaching the datetime object to display in a certain way on server level (meaning giving it an attribute like [Display(..)] or [DataType(...)] didn't force the date to look the way I want, so I simply wrote the following:
<input id="BirthDate" name="BirthDate" type="text" value="<%= Model.BirthDate.HasValue ? Model.BirthDate.Value.ToString("dd/MM/yyyy") : "" %>" class="text-box datepicker" />
However, even though I am specifically formatting the date to display "dd/MM/yyyy" in the input, it doesnt. When the browser settings are Dutch, the value inside this box is displayed with 'dd-MM-yyyy'.
I can somehow accept that, the browser is a smart guy(or gal) and identifies that the value in the box is a date and applies formatting according to the selected language settings. I don't know how to tell it not to screw with my dates, but I can get to believe that this is what happens. HOWEVER, what I am finding a lot difficult to accept is that THE Date formatting somehow goes back to the database. This sentance didnt really mean anything so I am explaining again. I have a table that has a few columns, one of them being a varchar(100). Super, and because of some very interesting designing, that field can contain text, dates and whatever.
So, because the field is a string, and later on I simply display it in a paragraph and dont need to do the whole dance of casting it to a DateTime object and then formatting it back when it gets in the view (which works so perfectly as I previously mentioned) I simply save it in the table in the correct format (dd/MM/yyyy).
Yea, but not really. My code would look like that:
var date = DateTime.Now;
db.EmployeeHistory log = new EmployeeHistory();
log.ActionType = 1;
log.EmployeeId = 1671;
log.At = date;
log.Context = "A TEST";
log.ObjectTitle = "Who cares";
log.EmployeeHistoryChangesSets.Add(new EmployeeHistoryChangesSet()
{ PropertyName = "TEST PROPERTY", NewValue = date.ToString("dd/MM/yyyy"), OldValue = date.ToString() });
dataContext.EmployeeHistories.InsertOnSubmit(log);
dataContext.SubmitChanges();
This is a of course a test, one that didnt make me happy at all. Because, if you are paying attention, there is a field in the database which is mapped to a string (varchar(...)) and then I am taking the Date, make it a string with the .ToString() method while formatting it into a "dd/MM/yyyy" format. So I am not using dates (well I am using a Date object to get the date, but I am converting it to a string) I am using only strings.
And somehow, for some reason that is truly escaping me, the string/date is saved in the database in the format: 'dd-MM-yyyy'. I really didnt expect it to behave in such a way. At first I was going to accept my fate, even though I was having a really hard time accepting that the database will take the liberty to format my input even though IT IS a string.
So, further testing showed me that the Date.ToString("dd/MM/yyyy") method actually returns the date in 'dd-MM-yyyy', depending on the browser language settings. Meaning that if I change my settings and it works correctly again ("dd/MM/yyyy").
So, my question is, what am I missing? Why is the .ToString() method not formatting the date correctly? Is my analisys correct or am I up and to the right on this one? If there is a good reason for that (even though I cant come up with one), should I just create my own extension method for DateTime class and implement the formatting mannualy or is there a better way?
I am really sorry for the long post (again). I would appreciate some clarity, as the whole project will behave this way. Thanks in advance

Designing Tests for Culture/Globalisation problems

I'm concerned about the predictability of my application in handling string input in different cultures. It has been a problem in older software and I don't want it to be a problem in the new.
I have generally two sources of input; Strings entered into a WPF application and Streams, loaded from files, containing text. These cultured strings are generally entered into an model before being used
public struct MyModel
{
public String Name;
}
I want to design a meaningful test to ensure some logic can actually handle Result DoSomething(MyModel model); when it contains text inputted on a different machine.
But how can I show a case where the difference matters?
For example the following fails.
var inNativeCulture= "[Something12345678.9:1] {YeS/nO}";
var inChineseCulture = inNativeCulture.ToString(new CultureInfo("zh-CN"));
Assert.That(inChineseCulture, Is.Not.EqualTo(inNativeCulture));
[Question]
How can I test DoSomething such that the test is able to fail if the strings are not converted to InvarientCulture?
Should I even bother? i.e. the string Something entered on a french keyboard will always equal Something entered on a Chinese keyboard?
What can I test for that will mitigate Globalization problems?
The ToString method taking a IFormatProvider on a string is essentially a no-op. The documentation states "Returns this instance of String; no actual conversion is performed."
Since you are concerned about avoiding issues here's some general advice. First it is very helpful to have a clear distinction in your mind between frontend (user facing) strings and backend (database, wire, file, etc) strings. Frontend strings should be generated/accepted according to the user's culture / application language. These strings should not be persisted (with few exceptions like when you are generating a document that will be read only by people and not by machine). Backend strings should always use standard formats that will not change over time. If you accept the fact that the data used to generate/parse globalized strings changes, then you will isolate yourself from the effects by ensuring that you do not persist user facing strings.

Format Financial Data like "2,000" as "2M" using a custom Format String with C# .NET WinForms and WPF Applications

We'd like to know if there is a way to format financial data such as "2,000" and "2,000,000" as "2M" and "2MM" respectively - essentially replacing the 1000's with M's.
Ideally there would be a format string we could use, such that 2000.0.ToString("X") would give us "2M" back and vice versa. Does such a formatstring exist? If not - is it possible to create one?
Note that these format strings work:
#,#,M – this will convert 2,000 to 2M (and back)
#,#,,MM – this will convert 2,000,00 to 2MM (and back)
#,#,,,B – this will convert 2,000,000,000 to 2B (and back)
However we need something more dynamic - something that can detect if it's any of these values and can apply the appropriate format string, if possible.
I don't know of a format to achieve what you want. You can, however, implement your own with the interfaces IFormatProvider and ICustomFormatter and pass this into the Format() and ToString() calls.

Categories

Resources