In my model I have a cNumber string, which can be different length (16,24 and 28), and I need to format it accordingly in my view in the table.
16 length: ########-########
24 : ########-########-########
28 : #### #### #### #### #### #### ####
UPDATE: I do have a method for the formatting, but I had a hard time passing it to the view to show up at the correct record of the table.
static string Format(string cNumber)
{
if (cNumber.Length == 16 || cNumber.Length == 24)
{
cNumber= Regex.Replace(cNumber, ".{8}", "$0-");
}
else if (cNumber.Length == 28)
{
cNumber= Regex.Replace(cNumber, ".{4}", "$0 ");
}
else
{
return cNumber;
}
cNumber= cNumber.Remove(cNumber.Length - 1);
return cNumber;
}
public ActionResult Index(Guid id)
{
var PartnerCNumbers = db.PartnerCNumbers.Include(p => p.Partner).Where(p=>p.Partner.PartnerGuid == id);
var cNumList = new List<string>();
foreach (var cn in PartnerCNumbers)
{
cNumList.Add(Format(cn.cNumber));
}
ViewData["cNumbers"] = cNumList;
ViewBag.PartnerGuid = id;
return View(PartnerCNumbers.ToList());
}
In my view i have the ViewData as a list
@model IEnumerable<Models.PartnerCNumbers>
IEnumerable<string> cNumbers= ViewData["cNumbers"] as IEnumerable<string>;
@foreach (var item in Model)
{
//int cLength = item.cNumber.Length;
<tr>
<td>
@Html.DisplayFor(modelItem => item.Currency)
</td>
<td>
//@Html.DisplayFor(modelItem => item.cNumber)
//THIS IS WHERE I NEED THE FORMATTED cNUMBER
</td>
<td>
@Html.DisplayFor(modelItem => item.sCode)
</td>
</tr>
}
Which is the best way to do it? I tried String.Format() in the view itself, but I couldn't convert it since it's already stored as a string in the database. Can a ViewModel have different annotations depending on a length attribute for example? Or is it somehow possible with javascript
I would create an Extension method for this type of "custom ToString"
public static class CNumberExtensions
{
static string ToFormattedCNumber(this string cNumber)
{
switch (cNumber.Length)
{
case 16:
return cNumber.Substring(0, 8) + "-"
+ cNumber.Substring(8);
case 24:
return cNumber.Substring(0, 8) + "-"
+ cNumber.Substring(8, 8) + "-"
+ cNumber.Substring(16);
case 28:
return cNumber.Substring(0, 4) + " "
+ cNumber.Substring(4, 4) + " "
+ cNumber.Substring(8, 4) + " "
+ cNumber.Substring(12, 4) + " "
+ cNumber.Substring(16, 4) + " "
+ cNumber.Substring(20, 4) + " "
+ cNumber.Substring(24);
}
throw new ArgumentException("cNumber length can only be 16, 24 or 28", nameof(cNumber));
}
}
Unless you are calling the function thousands of times per second, "the fastest way" is not necessarily the best.
You can use the following helper function in C# to format input strings by length as your requirement:
class Program
{
static string formatByLength(string s)
{
if (s.Length == 16)
{
return s.Substring(0, 8) + "-" + s.Substring(8);
}
if (s.Length == 24)
{
return s.Substring(0, 8) + "-" + s.Substring(8, 8) + "-" + s.Substring(16);
}
if (s.Length == 28)
{
var sb = new System.Text.StringBuilder();
for (var i = 0; i < 7; i++)
{
if (sb.Length > 0)
{
sb.Append(" ");
}
sb.Append(s.Substring(i * 4, 4));
}
return sb.ToString();
}
// return original string
return s;
}
static void Main(string[] args)
{
Console.WriteLine(formatByLength("1234567890123456"));
Console.WriteLine(formatByLength("123456789012345678901234"));
Console.WriteLine(formatByLength("1234567890123456789012345678"));
}
}
It outputs the following result:
12345678-90123456
12345678-90123456-78901234
1234 5678 9012 3456 7890 1234 5678
I would build a method to take a length of string with n fixed-length segments and then insert delimiters between:
private static string FormatNumberString(string input, int segmentLength, char delimiter)
{
StringBuilder builder = new StringBuilder();
// In a 16-length string, i will initially be 0, and then on the next
// iteration of the loop it will be 8
for (int i = 0; i < input.Length; i += segmentLength)
{
// if we're just starting another block we should add the delimiter
if (i != 0)
{
builder.Append(delimiter);
}
// add the section from i to i + segmentLength (e.g. 0-7 and then 8-15)
builder.Append(input.Substring(i, segmentLength));
}
return builder.ToString();
}
Then we can make a method to make calling this one easier:
private static string FormatNumberStringByLength(string input)
{
switch (input.Length)
{
// given the method above, 16 and 24-length strings have the same
// run length and delimiter, so we can group these together
case 16:
case 24:
return FormatNumberString(input, 8, '-');
case 28:
return FormatNumberString(input, 4, ' ');
default:
throw new ArgumentException("Input string length not recognized.", nameof(input));
}
}
Usage:
Console.WriteLine(FormatNumberStringByLength("1234567812345678"));
Console.WriteLine(FormatNumberStringByLength("123456781234567812345678"));
Console.WriteLine(FormatNumberStringByLength("1234123412341234123412341234"));
You should use cNumbers instead of the Model in the foreach loop.
IEnumerable<string> cNumbers= ViewData["cNumbers"] as IEnumerable<string>;
@foreach (var cNumber in cNumbers)
{
<tr>
<td>
//other model data
</td>
<td>
@cNumber
</td>
<td>
//other model data
</td>
</tr>
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.