Razor - how to get n number characters of string? - c#

I have an asp.net mvc 4 application with the following
Model
public string Price {get;set;}
it saves in database a string, eg. "41.99".
View
#foreach(var item in Model)
{
<div class="price">#item.Price</div>
}
it returns the value "41.99" all good here.
however I would like to pick the values differently.
Below is the Html output for what I need
#foreach(var item in Model)
{
<div class="price">
<span class="dollar">41</span>
<span class="cents">99</span>
</div>
}
Please Note that the value is split in 2 parts and the dot is left out.
The string will be inserted on input field as money, so it need to be inserted as "41.99"
Other consideration is if the value before the dot are 1, 11, 111, 1111 characters, it need display all numbers.
So how could I archive this?
#foreach(var item in Model)
{
<div class="price">
<span class="dollar">#item.Price(first part)</span>
<span class="cents">#item.Price(second part)</span>
</div>
}
Any help or guindance would be apprecciated.

If your data is string then
var price = "41.99";
var parts = price.Split('.');
var dollar = parts[0];
var cents = parts[1];
If your data is decimal
decimal price = 41.99m;
var dollar = (int)price;
var cents = (int)((price % 1) * 100);

Setting aside the fact you should not be using string to represent numerical values and use decimal instead for money values... and the fact that . is not the only separator (depending on locale)...
String.Split is the easiest way to split the string on a separator:
var parts = item.Price.Split(`.`);
Now you have parts[0] with "dollar" value, and need to deal with fractional part which may or may not be there. Note that you may need to pad cents value if you need something like 04 instead of just 4
#{
var parts = #item.Price.Split('.');
var cents = (parts.Length == 2) ? cents = parts[1] : "0";
}
<span class="dollar">#parts[0]</span>
<span class="cents">#cents</span>

Thanks for all replies
I figured it out combining the answers here with some suggestions.
here is the answer for my question:
Model:
public double Price { get; set; }
Controller:
public ActionResult Details(int id)
{
var data = _Context.Products.Where(d => d.ProductId == id).First();
if (data == null)
{
return HttpNotFound();
}
return View(data);
}
In View:
string s = Model.Price.ToString("0.00", System.Globalization.CultureInfo.InvariantCulture);
string[] parts = s.Split('.');
int i1 = int.Parse(parts[0]);
int i2 = int.Parse(parts[1]);
<span>#i1</span>
<span class="decimal">#i2</span>
Works like a charm
Thanks a lot

Related

C# String Remove characters between two characters

For Example i have string Like
"//RemoveFromhere
<div>
<p>my name is blawal i want to remove this div </p>
</div>
//RemoveTohere"
I want to use //RemoveFromhere as starting point from where
and //RemoveTohere as ending point in between all character i want to remove
var sin = "BEFORE//RemoveFromhere"+
"<div>"+
"<p>my name is blawal i want to remove this div </p>"+
"</div>"+
"//RemoveTohereAFTER";
const string fromId = "//RemoveFromhere";
const string toId = "//RemoveTohere";
var from = sin.IndexOf(fromId) + fromId.Length;
var to = sin.IndexOf(toId);
if (from > -1 && to > from)
Console.WriteLine(sin.Remove(from , to - from));
//OR to exclude the from/to tags
from = sin.IndexOf(fromId);
to = sin.IndexOf(toId) + toId.Length;
Console.WriteLine(sin.Remove(from , to - from));
This gives results BEFORE//RemoveFromhere//RemoveTohereAFTER and BEFOREAFTER
See also a more general (better) option using regular expressions from Cetin Basoz added after this answer was accepted.
void Main()
{
string pattern = #"\n{0,1}//RemoveFromhere(.|\n)*?//RemoveTohere\n{0,1}";
var result = Regex.Replace(sample, pattern, "");
Console.WriteLine(result);
}
static string sample = #"Here
//RemoveFromhere
<div>
<p>my name is blawal i want to remove this div </p>
</div>
//RemoveTohere
Keep this.
//RemoveFromhere
<div>
<p>my name is blawal i want to remove this div </p>
</div>
//RemoveTohere
Keep this too.
";

Regex for 4 digits including 0 at first position not working right

I need a regex which allows only 4 digits and those four can contain 0 at any position.
Below is my code:
View :
<label asp-for="UserId"></label><br />
<input asp-for="UserId" class="form-control" maxlength="4" />
<span asp-validation-for="UserId" class="text-danger"></span>
Model :
[RegularExpression(#"^([0-9]{4})$", ErrorMessage = "Please enter last 4 digits of your user Id.")]
[Display(Name = "Last 4 digits of user Id")]
public int? UserId{ get; set; }
But if I type in 0645, it throws an error "Please enter last 4 digits of your user Id.".If I change it to say 4567, it works fine. So how should I fix my regex?
You do not have any problem with your regex. As was already said in the comments, your property is an integer and when you set its value to 0645 internally it is converted to int and become 645.
If you look into RegularExpressionAttibute class, line 59, on GitHub you will realize that the method IsValid receives and object and then parses it as a string.
So lets look at the complete flow of your data.
1) Your user types a value into a textbox. ("0645")
2) ModelBinder converts the string typed into an integer. (645)
3) Inside RegularExpressionAttibute.IsValid your integer is converted again into an string ("645")
4) Regular Expression is applied to the value ("645") not ("0645"). So it will not pass your validation.
This is the RegularExpressionAttibute.IsValid method.
override bool IsValid(object value) {
this.SetupRegex();
// Convert the value to a string
string stringValue = Convert.ToString(value, CultureInfo.CurrentCulture);
// Automatically pass if value is null or empty. RequiredAttribute should be used to assert a value is not empty.
if (String.IsNullOrEmpty(stringValue)) {
return true;
}
Match m = this.Regex.Match(stringValue);
// We are looking for an exact match, not just a search hit. This matches what
// the RegularExpressionValidator control does
return (m.Success && m.Index == 0 && m.Length == stringValue.Length);
}
Whats the solution / suggestion?
You are expecting 4 digits as an input, and until now you don't said anything about have to do any kind of calculation with this.
As you don't need to do any calculation you can keep it as an string without any harm. Just keep validating that your string contains 4 digits (you are already doing it).
And if you need to do any calc in the future just convert the string to integer when its needed.
So just change this line:
public int? UserId{ get; set; }
To this:
public string UserId{ get; set; }

Limiting length of a phone number

I want a field for a phone number to take in a maximum of 10 digits. I have the [stringlength] attribute placed but I still cannot get the desired result. Thanks to those that can help me.
On a side note, is it possible to break apart the phone number so that the area code and the remaining digits get sent out separately to a db via a stored proc?
model:
public class Pharmacy
{
[StringLength(10,MinimumLength=10)]
public string PhoneNumber
{
get
{
return _phoneNumber;
}
set
{
Regex regexObj = new Regex(#"[^\d]");
_phoneNumber = regexObj.Replace(value, "");
_phoneNumber = Regex.Replace(_phoneNumber, #"(\d{3})(\d{3})(\d{4})", "($1) $2-$3");
}
}
}
form field:
<label id="lblPhoneNumber">Phone Number</label>
<input style="margin: 5px; " type=text name="txtPhoneNumber" id="txtPhoneNumber" value="#Model.Pharmacy.PhoneNumber" />
Why are you using HTML tags for the input if you're using ASP.NET MVC? You should really use Razor tags.
#Html.LabelFor(model => model.PhoneNumber, new { id = "lblPhoneNumber" })
#Html.TextBoxFor(model => model.PhoneNumber, new { id = "txtPhoneNumber", style="margin: 5px;", name="txtPhoneNumber", #Value = Model.Pharmacy.PhoneNumber })
#Html.ValidationFor(model => model.PhoneNumber, "", new { #class = "text-danger" })
Also, make sure you have unobtrusiveJS NuGet UnobtrusiveJS for the validation. Everything else seems fine with the data annotation. The unnamed parameter of [StringLength] is the maximum length, while you need to specify a minimum length. You might also want to let the user know about the error, so you'll need an error message as well [StringLength(10, MinimumLength=10, ErrorMessage="* Must be 10 digits")]
For the second part of the question
On a side note, is it possible to break apart the phone number so that the area code and the remaining digits get sent out separately to a db via a stored proc?
Yes, use RegEx capture groups, which you're already doing :).
RegEx regEx = new Regex(#"(\d{3})(\d{3})(\d{4})")
Matches matches = regex.Matches(value);
// matches[0] contains area code
// matches[1] contains first 3 digits
// matches[2] contains final 4 digits
MSDN - Regex.Matches

If string contains a letter, throw error?

passing in a list of strings :
List<string> quantity
if string contains all numbers, code is fine. However if user enters a 'letter' in the quantity section and submits the code breaks.
Need to do a check in the quantity list that it does not contain letters, if so return VIEW with error message:
foreach (string q in quantity)
{
if (q //if q == letter?)
{
_notifier.Information(T("A letter has been entered for quantity. Please enter a number"));
return Redirect(returnUrl);
}
}
How can I say is q is a letter?
thanks for any replies
You can use Char.IsLetter, here's a short LINQ version which checks if any string contains letters:
bool anyWrong = quantity.Any(s => s.Any(Char.IsLetter));
or the opposite way, check if all are valid using Char.IsDigit:
bool allCorrect = quantity.All(s => s.All(Char.IsDigit));
Another option is to check if all strings can be parsed to int or long, e.g.:
long l;
bool allCorrect = quantity.All(s => long.TryParse(s, out l));
If you also want to allow exponential notation, you can use decimal.TryParse with NumberStyles.Float:
List<string> quantity = new List<string> { "1000000000E-100" };
decimal d;
bool allCorrect = quantity
.All(s => decimal.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out d));
You can use a LINQ extension method for that:
if (!q.All(Char.IsDigit)) {
// not only digits
}
Since you have tagged this as MVC.. you should be using Data Annotations to validate your properties. E.g.:
public class YourModel {
public IList<QuantityModel> Quantities { get; set; }
}
public class QuantityModel {
[RegularExpression(#"\d+")] // <--- this
public int Amount { get; set; }
}
This saves you from manually validating your properties... as you are currently attempting to do.
Assuming that you accept positive integer numbers only, you should check if each string within list is not empty or null and contains anything but digits (not only letters that are 'A'..'Z', 'a'..'z' but, say '+', '{', command characters etc). You can do it by LINQ:
// All strings within quantity contains digits only
if (!quantity.All(c => (!String.IsNullOrEmpty(c)) && c.All(Char.IsDigit(c)))) {
_notifier.Information(T("A letter has been entered for quantity. Please enter a number"));
return Redirect(returnUrl);
}

Is it possible to implement the script in code behind

I have a javascript code which conver the amount in to US format the same i would like to have in code behind can any one help me..
<script type="text/javascript">
function formatCurrency(num) {
num = num.toString().replace(/\$|\,/g,'');
if(isNaN(num))
num = "0";
sign = (num == (num = Math.abs(num)));
num = Math.floor(num*100+0.50000000001);
cents = num%100;
num = Math.floor(num/100).toString();
if(cents<10)
cents = "0" + cents;
for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
num = num.substring(0,num.length-(4*i+3))+','+
num.substring(num.length-(4*i+3));
return (((sign)?'':'-') + '$' + num + '.' + cents);
}
</script>
Or if there is any easier method tell me. My actual requirement is to sum the two given amounts in the text boxes and to display the amount in 3rd text box.
For example if i have my 1st value as 123.12 by the above script i will get the display in my text box as $123.12 and second as same to $123.12 the output should be $246.23
can any one help me
There is a standard formatting for currency:
double n = 12345.67;
Console.WriteLine(n.ToString("C2", CultureInfo.GetCultureInfo("en-US")));
Ouptut:
$12,345.67
The standard for negative currency values is however to display it within parentheses, so if you want a negative sign instead you have to modify the culture:
CultureInfo info = new CultureInfo("en-US");
info.NumberFormat.CurrencyNegativePattern = 1;
double n = -12345.67;
Console.WriteLine(n.ToString("C2", info));
Ouptut:
-$12,345.67
If 123.12 + 123.12 = 246.23 then your customers might not be to happy
What type is num actually? It looks like it's just a number, but you're converting it to string, removing $ and , signs, just to add them later?
You can use decimal.ToString(string format) method, something like this should give you proper results:
static string Format(decimal x)
{
return x.ToString("$#,0.00", System.Globalization.CultureInfo.InvariantCulture);
}
//Usage:
string currencyFormatedNumber = Format(-41023.43M); //returns -$41,023.43
You could use something like this:
static string Format(decimal x)
{
return x.ToString("C", System.Globalization.CultureInfo.GetCultureInfo("en-us"));
}
which is used to format currency, but it will format negative numbers as they should be formatted ($100.00) means -100.00 dollars, which differs from your code.

Categories

Resources