MVC3 Display Templates Truncate String - asp.net-mvc-3

I have created a custom Display For template that will be used mainly in my index file so that when the records are shown in the lists, they are not turned into ugly looking creature if some records are way too lengthy. I have tried following:
#model string
#{
string text = Html.Encode(Model??"");
if (text.Length >= 35)
{
text = text.Substring(0, 35)+"...";
}
#Html.DisplayFor(model=>text)
}
Though it works fine for the strings having length more than 35 or equal to it, but it doesn't work if the string is lesser than that. I have tried the else statement, but it doesn't work either.
What is the correct way to do this?
Edit: Null string. In the source page file, between the two there is nothing.

try this for the template
#model string
#{
string text = Html.Encode(Model ?? "");
if (text.Length >= 35)
{
text = text.Substring(0, 35) + "...";
}
}
#text

Related

When TextBox.Text is set to string.Empty explicitly it starts to add each next char to the beginning

When TextBox.Text is set to string.Empty explicitly it starts to add each next char to the beginning.
That is, after I set TextBox.Text = string.Empty,
I tap on the TextBox and start to click on the virtual keyboard keys,
for example in the following order: ABCD
But textbox will show DCBA instead.
What is that and how to force the TextBox to insert keys into a proper place?
Have you tried setting to ""? That works for me.
TextBox.Text = "";
Although, honestly, there should be no difference between the two. I have plenty of TextBoxes reset to "" and this problem hasn't occurred for me.
The effect described above was triggered by the fact that the property to which it was binded called ToUpper() on value:
private string word;
public string Word {
get { return word; }
set {
word = value.ToUpper();
NotifyOfPropertyChange(() => Word);
}
}
Seems like a bug somewhere.

Remove HTML formatting in Razor MVC 3

I am using MVC 3 and Razor View engine.
What I am trying to do
I am making a blog using MVC 3, I want to remove all HTML formatting tags like <p> <b> <i> etc..
For which I am using the following code. (it does work)
#{
post.PostContent = post.PostContent.Replace("<p>", " ");
post.PostContent = post.PostContent.Replace("</p>", " ");
post.PostContent = post.PostContent.Replace("<b>", " ");
post.PostContent = post.PostContent.Replace("</b>", " ");
post.PostContent = post.PostContent.Replace("<i>", " ");
post.PostContent = post.PostContent.Replace("</i>", " ");
}
I feel that there definitely has to be a better way to do this. Can anyone please guide me on this.
Thanks Alex Yaroshevich,
Here is what I use now..
post.PostContent = Regex.Replace(post.PostContent, #"<[^>]*>", String.Empty);
The regular expression is slow. use this, it's faster:
public static string StripHtmlTagByCharArray(string htmlString)
{
char[] array = new char[htmlString.Length];
int arrayIndex = 0;
bool inside = false;
for (int i = 0; i < htmlString.Length; i++)
{
char let = htmlString[i];
if (let == '<')
{
inside = true;
continue;
}
if (let == '>')
{
inside = false;
continue;
}
if (!inside)
{
array[arrayIndex] = let;
arrayIndex++;
}
}
return new string(array, 0, arrayIndex);
}
You can take a look at http://www.dotnetperls.com/remove-html-tags
Just in case you want to use regex in .NET to strip the HTML tags, the following seems to work pretty well on the source code for this very page. It's better than some of the other answers on this page because it looks for actual HTML tags instead of blindly removing everything between < and >. Back in the BBS days, we typed <grin> a lot instead of :), so removing <grin> is not an option. :)
This solution only removes the tags. It does not remove the contents of those tags in situations where that might be important -- a script tag, for example. You'd see the script, but the script wouldn't execute because the script tag itself gets removed. Removing the contents of an HTML tag is VERY tricky, and practically requires that the HTML fragment be well formed...
Also note the RegexOption.Singleline option. That's very important for any block of HTML. as there's nothing wrong with opening an HTML tag on one line and closing it in another.
string strRegex = #"</{0,1}(!DOCTYPE|a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|datalist|dd|del|details|dfn|dialog|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|main|map|mark|menu|menuitem|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr){1}(\s*/{0,1}>|\s+.*?/{0,1}>)";
Regex myRegex = new Regex(strRegex, RegexOptions.Singleline);
string strTargetString = #"<p>Hello, World</p>";
string strReplace = #"";
return myRegex.Replace(strTargetString, strReplace);
I'm not saying this is the best answer. It's just an option and it worked great for me.

Jsoup css selector code (xpath code included)

I am trying to parse below HTML using jsoup but not able to get the right syntax for it.
<div class="info"><strong>Line 1:</strong> some text 1<br>
<b>some text 2</b><br>
<strong>Line 3:</strong> some text 3<br>
</div>
I need to capture some text 1, some text 2 and some text 3 in three different variables.
I have the xpath for first line (which should be similar for line 3) but unable to work out the equivalent css selector.
//div[#class='info']/strong[1]/following::text()
On a separate I have few hundred html files and need to parse and extract data from them to store in a database. Is Jsoup best choice for this?
It really looks like Jsoup can't handle getting text out of an element with mixed content. Here is a solution that uses the XPath you formulated that uses XOM and TagSoup:
import java.io.IOException;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Nodes;
import nu.xom.ParsingException;
import nu.xom.ValidityException;
import nu.xom.XPathContext;
import org.ccil.cowan.tagsoup.Parser;
import org.xml.sax.SAXException;
public class HtmlTest {
public static void main(final String[] args) throws SAXException, ValidityException, ParsingException, IOException {
final String html = "<div class=\"info\"><strong>Line 1:</strong> some text 1<br><b>some text 2</b><br><strong>Line 3:</strong> some text 3<br></div>";
final Parser parser = new Parser();
final Builder builder = new Builder(parser);
final Document document = builder.build(html, null);
final nu.xom.Element root = document.getRootElement();
final Nodes textElements = root.query("//xhtml:div[#class='info']/xhtml:strong[1]/following::text()", new XPathContext("xhtml", root.getNamespaceURI()));
for (int textNumber = 0; textNumber < textElements.size(); ++textNumber) {
System.out.println(textElements.get(textNumber).toXML());
}
}
}
This outputs:
some text 1
some text 2
Line 3:
some text 3
Without knowing more specifics of what you're trying to do though, I'm not sure if this is exactly what you want.
It is possible to get an object reference to individual TextNodes. I think maybe you over looked Jsoup's TextNode Object.
The text at the top level of an Element is an instance of a TextNode Object. For instance, " some text 1" and " some text 3" are both TextNode Objects under "< div class='info' >" and "Line 1:" is a TextNode Object under "< strong >"
Element Objects have a textNodes() method which will be of use for you to get a hold of these TextNode Objects.
Check the following code:
String html = "<html>" +
"<body>" +
"<div class="info">" +
"<strong>Line 1:</strong> some text 1<br>" +
"<b>some text 2</b><br>" +
"<strong>Line 3:</strong> some text 3<br>" +
"</div>" +
"</body>" +
"</html>";
Document document = JSoup.parse(html);
Element infoDiv = document.select("div.info").first();
List<TextNode> infoDivTextNodes = infoDiv.textNodes();
This code finds the first < div > Element who has an Attribute with key="class" and value="info". Then get a reference to all of the TextNode Objects directly under "< div class='info' >". That list looks like:
List<TextNode>[" some text 1", " some text 3"]
TextNode Objects have some sweet data and methods associated with them which you can utilize, and extends Node giving you even more functionality to utilize.
The following is an example of getting object references for each TextNode inside div's with class="info".
for(Iterator<Element> elementIt = document.select("div.info").iterator(); elementIt.hasNext();){
Element element = elementIt.next();
for (Iterator<TextNode> textIt = element.textNodes().iterator(); textIt.hasNext();) {
TextNode textNode = textIt.next();
//Do your magic with textNode now.
//You can even reference it's parent via the inherited Node Object's
//method .parent();
}
}
Using this nested iterator technique you can access all the text nodes of an object and with some clever logic you can just about do anything you want within Jsoup's structure.
I have implemented this logic for a spell checking method I have created in the past and it does have some performance hits on very large html documents with a high number of elements, perhaps a lot of lists or something. But if your files are reasonable in length, you should get sufficient performance.
The following is an example of getting object references for each TextNode of a Document.
Document document = Jsoup.parse(html);
for (Iterator<Element> elementIt = document.body().getAllElements().iterator(); elementIt.hasNext();) {
Element element = elementIt.next();
//Maybe some magic for each element..
for (Iterator<TextNode> textIt = element.textNodes().iterator(); textIt.hasNext();) {
TextNode textNode = textIt.next();
//Lots of magic here for each textNode..
}
}
Your problem I think is that of the text you're interested in, only one phrase is enclosed within any defining tags, "some text 2" which is enclosed by <b> </b> tags. So this is easily obtainable via:
String text2 = doc.select("div.info b").text();
which returns
some text 2
The other texts of interest can only be defined as text held within your <div class="info"> tag, and that's it. So the only way that I know of to get this is to get all the text held by this larger element:
String text1 = doc.select("div.info").text();
But unfortunately, this gets all the text held by this element:
Line 1: some text 1 some text 2 Line 3: some text 3
That's about the best I can do, and I'm hoping someone can find a better answer and will keep following this question.

Textarea and StringLength validator on server side count 'enter' as two characters

I have a StringLength validator on textarea
[StringLength(10, ErrorMessage = "The {0} must be {1} characters or less")]
So when I press enter and then type 9 characters, the client validation does not display any errors; but if I submit the form, server validation says that there is more than 10 characters.
So on client side enter means one character and on server, two. It is not the same behavior.
Probably I would need to implement my own validator which would do it, right?
Or is there any validators I may use instead of StringLength, to validate textarea content length correctly?
See my answer here: New line characters in text area increases text length in C#
You can change the default behavior for getLength to double count newlines by adding the following to your JS somewhere.
$.validator.prototype._getLength = $.validator.prototype.getLength;
$.validator.prototype.getLength = function (value, element) {
// Double count newlines in a textarea because they'll be turned into \r\n by the server.
if (element.nodeName.toLowerCase() === 'textarea')
return value.length + value.split('\n').length - 1;
return this._getLength(value, element);
};
Add attribute to your property
[RegularExpression(#"^[\s\S]{0,10}$",ErrorMessage="maximun length must be 10")]
then in your view
<%: Html.ValidationMessageFor(m => m.MyText) %>
I had the same issue recently, but since both the .Net code and Sql Server were considering one line break as two chars, I ended up changing the client side logic to also consider line breaks as two chars:
$('textarea[maxlength]').keyup(function () {
var lineBreaks = $(this).val().split('\n').length - 1;
var charsUsed = $(this).val().length + lineBreaks;
if (charsUsed >= maxlength) {
$(this).val($(this).val().substr(0, maxlength - lineBreaks));
charsUsed = maxlength;
}
var remaining = maxlength - charsUsed;
$('#MyCounter').html("<strong>" + remaining + "</strong> characters remaining");
});

T4 FieldName in camelCase without Underscore?

I'm using T4 to generate some class definitions and find that I'm getting an underscore in front of my field names.
I have set
code.CamelCaseFields = true;
just to be safe (even though I understand that's the default) but still end up with _myField rather than myField.
How can I generate a field name without the '_' character?
Also, where is the documentation for T4? I'm finding plenty of resources such as
Code Generation and Text Templates and numerous blogs, but I have not found the class-by-class, property-by-property documentation.
You're probably talking about EF4 Self Tracking Entities. The CodeGenerationTools class is included via the <## include file="EF.Utility.CS.ttinclude"#> directive, which you can find at "[VSInstallDir]\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\Templates\Includes\EF.Utility.CS.ttinclude".
The FieldName function is defined as such:
private string FieldName(string name)
{
if (CamelCaseFields)
{
return "_" + CamelCase(name);
}
else
{
return "_" + name;
}
}
The "_" is hardcoded in the function. Coding your own shouldn't be difficult. Note that the CodeGenerationTools class is specific to this ttinclude file and isn't a generic and embedded way to generate code in T4.
I've written the following method to make first character upper case, remove spaces/underscores and make next character upper case. See samples below. Feel free to use.
private string CodeName(string name)
{
name = name.ToLowerInvariant();
string result = name;
bool upperCase = false;
result = string.Empty;
for (int i = 0; i < name.Length; i++)
{
if (name[i] == ' ' || name[i] == '_')
{
upperCase = true;
}
else
{
if (i == 0 || upperCase)
{
result += name[i].ToString().ToUpperInvariant();
upperCase = false;
}
else
{
result += name[i];
}
}
}
return result;
}
input/output samples:
first_name = FirstName,
id = Id,
status message = StatusMessage
This is good advice however it doesn't help you in knowing WHERE the right place to put such a function is...
Is there any guidance on DECOMPOSING the EF .tt files or stepping through the output generation to see how it builds the output?
I was able to use the above function successfully by plugging it into a function called
(Ef4.3)
public string Property(EdmProperty edmProperty)
Which appears to be used to output the lines like "public int fieldname { get; set; }"
and changed the 3rd (index {2}) param to the formating to wrap with the function to modify the name, like this:
_typeMapper.GetTypeName(edmProperty.TypeUsage), //unchanged
UnderScoreToPascalCase(_code.Escape(edmProperty)), //wrapped "name"
_code.SpaceAfter(Accessibility.ForGetter(edmProperty)), // unchanged
This is not perfect, eg: it doesn't keep existing "Ucasing" and doesn't care about things like this:
customerIP
outputs: Customerip
which IMO is not very readable...
but its better than what I WAS looking at which was a nightmare because the database was intermingled mess of camelCase, PascalCase and underscore separation, so pretty horrific.
anyway hope this helps someone...

Resources