On an ASP.NET MVC I have a textarea as follows:
#Html.TextAreaFor(x => x.Text, 12, 12, null)
On the controller I am defining the model as:
NewPostModel model = new NewPostModel() { Text = #"First line\r\n\r\nan\[x \cdot y\]" };
But in the view I don't have a break line inside the textbox.
The text appears all in the same line. Why?
UPDATE
I isolated the problem ... If it don't use # before the string then it works.
The problem is that in the string I have parts as [ and ( ...
And then I get an error: Unrecognized escape sequence.
How can I solve this?
Thank You,
Miguel
If you can edit your string, you can do something like this and avoid so the use of the # :
var model = new NewPostModel() { Text = "First line\r\n\r\nan\\[x \\cdot y\\]" };
Related
In my unit test, I'm trying to assert that a user can access and select an item from a dropdown menu. I have built every .FindElement() extension I can do, but when running the Unit Test it isn't finding the dropdown menu. Could anybody help me figure out how to select it? The list of dropdown items comes from a list built elsewhere in the code base.
# Syncfusion Dropdown List Code
<SfDropDownList TItem="Industry" TValue="string" Placeholder="Select..." PopupHeight="20px" DataSource="#Industries" AllowFiltering="true" #bind-Value="Industry" ID="industry">
<DropDownListEvents TItem="Industry" TValue="string" ValueChange="#(ChangeIndustry)"></DropDownListEvents>
<DropDownListFieldSettings Text="IndustryName"></DropDownListFieldSettings>
</SfDropDownList>
#Test
var industry = driver.FindElement(By.Id("industry"));
var selectElement = new SelectElement(industry);
selectElement.SelectByText("Construction");
//Assert
Assert.Contains("Construction", industry.Text);
#HTML
<div class="mb-2 position-relative">
<label class="label-client" for="Industry">Industry</label>
-- <Dropdown Code Above> --
</div>
So the XPath I was using was wrong, even though I'd followed it through with the generated HTML, I installed the Selenium Edge Extension and used this to record the test I was doing. There is an option in there to change the outputs from CSS select to XPath, which gave me the correct path I was looking for.
I think it must be something to do with the way Syncfusion components generate once the browser is loaded up, but the class and IDs were completely different to the ones I had thought they were. Thanks for the help #JeffC!
The SelectElement class is only for the SELECT HTML element and can't be used here. You'll have to click the element to open the dropdown and then find the desired element based on text contained using an XPath. You haven't provided the HTML generated in the browser for the dropdown so I can't provide a specific locator but this should give you the general idea.
var industry = driver.FindElement(By.Id("industry"));
industry.click(); // open the dropdown
driver.FindElement(By.XPath("//*[.='Sample option']")).click();
You can also use the below code to select the value in the dropdown.
[Fact(DisplayName = "Select item when click the list item")]
public async Task SelectItem()
{
var data = GetDataItems();
var dropdown = RenderComponent<SfDropDownList<string, Countries>>(parameters =>
parameters.Add(p => p.DataSource, data).AddChildContent<DropDownListFieldSettings>(field => field.Add(p => p.Text, "Name").Add(p => p.Value, "Code")));
await dropdown.Instance.ShowPopup();
var popupEle = dropdown.Find(".e-popup");
var liColl = popupEle.QuerySelectorAll("li.e-list-item");
liColl[3].Click();
Assert.Contains("e-active", liColl[3].ClassName);
Assert.Contains("Cameroon", dropdownlist.Instance.Text);
var focusItem = popupEle.QuerySelector("li.e-item-focus");
Assert.Null(focusItem);
}
private List<Countries> GetDataItems()
{
return new List<Countries>
{
new Countries() { Name = "Australia", Code = "AU" },
new Countries() { Name = "Bermuda", Code = "BM" },
new Countries() { Name = "Canada", Code = "CA" },
new Countries() { Name = "Cameroon", Code = "CM" },
new Countries() { Name = "Denmark", Code = "DK" },
new Countries() { Name = "France", Code = "FR" }
};
}
The following is supposed to work as so:
User enters value "Apartment 101" in the "Apartment/Space/Other" search field.
The "Apartment" part of the value is replaced by an empty string ("").
Records with values that include "101" are displayed in the search results. This can include "Space 101", "Num 101", "Apartment 101", etc.
Currently, if I enter "Apartment 101", the search results include only records with "Apartment 101".
var apartment = Request.Form.GetValues("columns[1][search][value]")[0];
if (!string.IsNullOrWhiteSpace(apartment))
{
if (apartment.Contains("Num"))
apartment.Replace("Num", "");
if (apartment.Contains("Apartment"))
apartment.Replace("Apartment", "");
if (apartment.Contains("Space"))
apartment.Replace("Space", "");
data = data.Where(gsn => gsn.Apartment.Contains(apartment));
}
I tried using the Contains function to see if a certain string is in the value entered. If it is, then I tried using the Replace function to replace that value with an empty string ("").
When I search for a value, such as "Space 301", I expect to see all records with "301" in the search results.
string.replace returns the value and does not change the main variable so change it to something like this:
if (!string.IsNullOrWhiteSpace(apartment))
{
if (apartment.Contains("Num")){
apartment = apartment.Replace("Num", "");
data = data.Where(gsn => gsn.Num.Contains(apartment));
}else
if (apartment.Contains("Apartment")){
apartment = apartment.Replace("Apartment", "");
data = data.Where(gsn => gsn.Apartment.Contains(apartment));
}else
if (apartment.Contains("Space")){
apartment = apartment.Replace("Space", "");
data = data.Where(gsn => gsn.Space.Contains(apartment));
}
}
This question already has answers here:
fastest way to replace string in a template
(9 answers)
Closed 4 months ago.
I have a question, my template content does not have a fixed value, this template content value is random and comes from what the user input and stores in the table, but the variable of the content is set.
For example few template content values (For schedule.TemplateContent) :
1. My name is {name}.
2. My name is {name}. My last name is {lastName}
3. Her name is {name}. She is a {sex}. She like play {activity}
Below is my code, I just only know how to replace 1 word in the template content, not sure how to replace if loop the template content has multiple variables need to replace:
foreach (SAASQueuePatList pat in patList)
{
pat.PatName = "{name}";
pat.PatLastName = "{lastName}";
pat.PatSex= "{sex}";
pat.PatActivity = "{activity}";
string fullContent = schedule.TemplateContent.Replace("{name}", pat.PatName);
}
Hope someone can guide me on how to solve this problem. Thanks.
string fullContent = schedule.TemplateContent
.Replace("{name}", pat.PatName)
.Replace("{lastName}", pat.PatLastName)
.Replace("{sex}", pat.PatSex)
.Replace("{activity}", pat.PatActivity);
You need a map that links a field name to a property.
var map = new Dictionary<string,Func<SAASQueuePat,string>>
{
"name", x => x.PatName,
"sex", x => x.Gender
};
Then you can generate string like this:
foreach (var item in map)
{
template = template.Replace("{" + item.Key + "}", item.Value(pat));
}
I'm writing a function that will parse a file similar to an XML file from a legacy system.
....
<prod pid="5" cat='gov'>bla bla</prod>
.....
<prod cat='chi'>etc etc</prod>
....
.....
I currently have this code:
buf = Regex.Replace(entry, "<prod(?:.*?)>(.*?)</prod>", "<span class='prod'>$1</span>");
Which was working fine until it was decided that we also wanted to show the categories.
The problem is, categories are optional and I need to run the category abbreviation through a SQL query to retrieve the category's full name.
eg:
SELECT * FROM cats WHERE abbr='gov'
The final output should be:
<span class='prod'>bla bla</span><span class='cat'>Government</span>
Any idea on how I could do this?
Note1: The function is done already (except this part) and working fine.
Note2: Cannot use XML libraries, regex has to be used
Regex.Replace has an overload that takes a MatchEvaluator, which is basically a Func<Match, string>. So, you can dynamically generate a replacement string.
buf = Regex.Replace(entry, #"<prod(?<attr>.*?)>(?<text>.*?)</prod>", match => {
var attrText = match.Groups["attr"].Value;
var text = match.Groups["text"].Value;
// Now, parse your attributes
var attributes = Regex.Matches(#"(?<name>\w+)\s*=\s*(['""])(?<value>.*?)\1")
.Cast<Match>()
.ToDictionary(
m => m.Groups["name"].Value,
m => m.Groups["value"].Value);
string category;
if (attributes.TryGetValue("cat", out category))
{
// Your SQL here etc...
var label = GetLabelForCategory(category)
return String.Format("<span class='prod'>{0}</span><span class='cat'>{1}</span>", WebUtility.HtmlEncode(text), WebUtility.HtmlEncode(label));
}
// Generate the result string
return String.Format("<span class='prod'>{0}</span>", WebUtility.HtmlEncode(text));
});
This should get you started.
I have the following model which is wrapped in my view model
public class FloorPlanSettingsModel
{
public int Id { get; set; }
public int? MainFloorPlanId { get; set; }
public string ImageDirectory { get; set; }
public string ThumbnailDirectory { get; set; }
public string IconsDirectory { get; set; }
}
How do I access one of the above properties from Javascript?
I tried this, but I got "undefined"
var floorplanSettings = "#Model.FloorPlanSettings";
alert(floorplanSettings.IconsDirectory);
You could take your entire server-side model and turn it into a Javascript object by doing the following:
var model = #Html.Raw(Json.Encode(Model));
In your case if you just want the FloorPlanSettings object, simply pass the Encode method that property:
var floorplanSettings = #Html.Raw(Json.Encode(Model.FloorPlanSettings));
Contents of the Answer
1) How to access Model data in Javascript/Jquery code block in .cshtml file
2) How to access Model data in Javascript/Jquery code block in .js file
How to access Model data in Javascript/Jquery code block in .cshtml file
There are two types of c# variable (Model) assignments to JavaScript variable.
Property assignment - Basic datatypes like int, string, DateTime (ex: Model.Name)
Object assignment - Custom or inbuilt classes (ex: Model, Model.UserSettingsObj)
Lets look into the details of these two assignments.
For the rest of the answer lets consider the below AppUser Model as an example.
public class AppUser
{
public string Name { get; set; }
public bool IsAuthenticated { get; set; }
public DateTime LoginDateTime { get; set; }
public int Age { get; set; }
public string UserIconHTML { get; set; }
}
And the values we assign this Model are
AppUser appUser = new AppUser
{
Name = "Raj",
IsAuthenticated = true,
LoginDateTime = DateTime.Now,
Age = 26,
UserIconHTML = "<i class='fa fa-users'></i>"
};
Property assignment
Lets use different syntax for assignment and observe the results.
1) Without wrapping property assignment in quotes.
var Name = #Model.Name;
var Age = #Model.Age;
var LoginTime = #Model.LoginDateTime;
var IsAuthenticated = #Model.IsAuthenticated;
var IconHtml = #Model.UserIconHTML;
As you can see there are couple of errors, Raj and True is considered to be javascript variables and since they dont exist its an variable undefined error. Where as for the dateTime varialble the error is unexpected number numbers cannot have special characters, The HTML tags are converted into its entity names so that the browser doesn't mix up your values and the HTML markup.
2) Wrapping property assignment in Quotes.
var Name = '#Model.Name';
var Age = '#Model.Age';
var LoginTime = '#Model.LoginDateTime';
var IsAuthenticated = '#Model.IsAuthenticated';
var IconHtml = '#Model.UserIconHTML';
The results are valid, So wrapping the property assignment in quotes gives us valid syntax. But note that the Number Age is now a string, So if you dont want that we can just remove the quotes and it will be rendered as a number type.
3) Using #Html.Raw but without wrapping it in quotes
var Name = #Html.Raw(Model.Name);
var Age = #Html.Raw(Model.Age);
var LoginTime = #Html.Raw(Model.LoginDateTime);
var IsAuthenticated = #Html.Raw(Model.IsAuthenticated);
var IconHtml = #Html.Raw(Model.UserIconHTML);
The results are similar to our test case 1. However using #Html.Raw()on the HTML string did show us some change. The HTML is retained without changing to its entity names.
From the docs Html.Raw()
Wraps HTML markup in an HtmlString instance so that it is interpreted as HTML markup.
But still we have errors in other lines.
4) Using #Html.Raw and also wrapping it within quotes
var Name ='#Html.Raw(Model.Name)';
var Age = '#Html.Raw(Model.Age)';
var LoginTime = '#Html.Raw(Model.LoginDateTime)';
var IsAuthenticated = '#Html.Raw(Model.IsAuthenticated)';
var IconHtml = '#Html.Raw(Model.UserIconHTML)';
The results are good with all types. But our HTML data is now broken and this will break the scripts. The issue is because we are using single quotes ' to wrap the the data and even the data has single quotes.
We can overcome this issue with 2 approaches.
1) use double quotes " " to wrap the HTML part. As the inner data has only single quotes. (Be sure that after wrapping with double quotes there are no " within the data too)
var IconHtml = "#Html.Raw(Model.UserIconHTML)";
2) Escape the character meaning in your server side code. Like
UserIconHTML = "<i class=\"fa fa-users\"></i>"
Conclusion of property assignment
Use quotes for non numeric dataType.
Do Not use quotes for numeric dataType.
Use Html.Raw to interpret your HTML data as is.
Take care of your HTML data to either escape the quotes meaning in server side, Or use a different quote than in data during assignment to javascript variable.
Object assignment
Lets use different syntax for assignment and observe the results.
1) Without wrapping object assignment in quotes.
var userObj = #Model;
When you assign a c# object to javascript variable the value of the .ToString() of that oject will be assigned. Hence the above result.
2 Wrapping object assignment in quotes
var userObj = '#Model';
3) Using Html.Raw without quotes.
var userObj = #Html.Raw(Model);
4) Using Html.Raw along with quotes
var userObj = '#Html.Raw(Model)';
The Html.Raw was of no much use for us while assigning a object to variable.
5) Using Json.Encode() without quotes
var userObj = #Json.Encode(Model);
//result is like
var userObj = {"Name":"Raj",
"IsAuthenticated":true,
"LoginDateTime":"\/Date(1482572875150)\/",
"Age":26,
"UserIconHTML":"\u003ci class=\"fa fa-users\"\u003e\u003c/i\u003e"
};
We do see some change, We see our Model is being interpreted as a object. But we have those special characters changed into entity names. Also wrapping the above syntax in quotes is of no much use. We simply get the same result within quotes.
From the docs of Json.Encode()
Converts a data object to a string that is in the JavaScript Object Notation (JSON) format.
As you have already encountered this entity Name issue with property assignment and if you remember we overcame it with the use of Html.Raw. So lets try that out. Lets combine Html.Raw and Json.Encode
6) Using Html.Raw and Json.Encode without quotes.
var userObj = #Html.Raw(Json.Encode(Model));
Result is a valid Javascript Object
var userObj = {"Name":"Raj",
"IsAuthenticated":true,
"LoginDateTime":"\/Date(1482573224421)\/",
"Age":26,
"UserIconHTML":"\u003ci class=\"fa fa-users\"\u003e\u003c/i\u003e"
};
7) Using Html.Raw and Json.Encode within quotes.
var userObj = '#Html.Raw(Json.Encode(Model))';
As you see wrapping with quotes gives us a JSON data
Conslusion on Object assignment
Use Html.Raw and Json.Encode in combintaion to assign your object to javascript variable as JavaScript object.
Use Html.Raw and Json.Encode also wrap it within quotes to get a JSON
Note: If you have observed the DataTime data format is not right. This is because as said earlier Converts a data object to a string that is in the JavaScript Object Notation (JSON) format and JSON does not contain a date type. Other options to fix this is to add another line of code to handle this type alone using javascipt Date() object
var userObj.LoginDateTime = new Date('#Html.Raw(Model.LoginDateTime)');
//without Json.Encode
How to access Model data in Javascript/Jquery code block in .js file
Razor syntax has no meaning in .js file and hence we cannot directly use our Model insisde a .js file. However there is a workaround.
1) Solution is using javascript Global variables.
We have to assign the value to a global scoped javascipt variable and then use this variable within all code block of your .cshtml and .js files. So the syntax would be
<script type="text/javascript">
var userObj = #Html.Raw(Json.Encode(Model)); //For javascript object
var userJsonObj = '#Html.Raw(Json.Encode(Model))'; //For json data
</script>
With this in place we can use the variables userObj and userJsonObj as and when needed.
Note: I personally dont suggest using global variables as it gets very hard for maintainance. However if you have no other option then you can use it with having a proper naming convention .. something like userAppDetails_global.
2) Using function() or closure
Wrap all the code that is dependent on the model data in a function. And then execute this function from the .cshtml file .
external.js
function userDataDependent(userObj){
//.... related code
}
.cshtml file
<script type="text/javascript">
userDataDependent(#Html.Raw(Json.Encode(Model))); //execute the function
</script>
Note: Your external file must be referenced prior to the above script. Else the userDataDependent function is undefined.
Also note that the function must be in global scope too. So either solution we have to deal with global scoped players.
try this: (you missed the single quotes)
var floorplanSettings = '#Html.Raw(Json.Encode(Model.FloorPlanSettings))';
Wrapping the model property around parens worked for me. You still get the same issue with Visual Studio complaining about the semi-colon, but it works.
var closedStatusId = #(Model.ClosedStatusId);
I know its too late but this solution is working perfect for both .net framework and .net core:
#System.Web.HttpUtility.JavaScriptStringEncode()
For MVC 4
#model Inventory.Models.PurchaseVModel
#{
ViewData["Title"] = "Add";
Layout = "~/Views/Shared/_Layout.cshtml";
var jsonItems = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model.Items);
}
#section scripts{
<script>
$(document).ready(function () {
var allItem = #Html.Raw(jsonItems);
console.log(allItem);
});
</script>
}
.Net Core 3.1
#model Inventory.Models.PurchaseVModel
#{
ViewData["Title"] = "Add";
Layout = "~/Views/Shared/_Layout.cshtml";
var jsonItems = Newtonsoft.Json.JsonConvert.SerializeObject(Model.Items);
}
#section scripts{
<script>
$(document).ready(function () {
var allItem = #Html.Raw(jsonItems);
console.log(allItem);
});
</script>
}
I used the following to convert a Model object passed from the controller in the Razor view to JSON Object in JavaScript. This worked perfectly for me in ASP.Net Core.
<script>
let jsonData = #Html.Raw(Json.Serialize(Model))
console.log(jsonData)
</script>
In addition to #Rajshekar's thorough answer, I prefer a helper method that returns a IHtmlString value, which Razor recognizes as already-encoded HTML. Then, the Html.Raw() wrapper isn't needed, improving readability.
public static class JSHelper
{
/// <summary>
/// Encode a value as a JSON value or object for use in JavaScript code.
/// </summary>
/// <param name="value">Value to encode.</param>
/// <returns>HTML string containing the JavaScript value or object.</returns>
public static IHtmlString JsonEncode(object value)
{
return MvcHtmlString.Create(Json.Encode(value));
}
}
Then I can just use, obj = #JSHelper.JsonEncode(myObject); in my JavaScript section.
Include a using clause in your view or update view/web.config to resolve the namespace within the view.
So here is how we do it in .net core razor pages.
#section scripts
{
<script>
$(document).ready(function () {
leaveStatusDictionary = #Html.Raw(Json.Serialize(Model.LeaveStatusDictionary));
});
function GetStatusName(status) {
return window.leaveStatusDictionary[status];
}
</script>
}
Note the following.
I did not use var keyword before leaveStatusDictionary. So this now a property on the window object. So I was able to access that in a different js function - GetStatusName you see there.
LeaveStatusDictionary is a property on the model class of type Dictionary<int, string>.
If "ReferenceError: Model is not defined" error is raised, then you might try to use the following method:
$(document).ready(function () {
#{ var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = serializer.Serialize(Model);
}
var model = #Html.Raw(json);
if(model != null && #Html.Raw(json) != "undefined")
{
var id= model.Id;
var mainFloorPlanId = model.MainFloorPlanId ;
var imageDirectory = model.ImageDirectory ;
var iconsDirectory = model.IconsDirectory ;
}
});