How do I get value instead of reference from icollection when pullling in cshtml - razor

I am trying to display the values of an icollection in cshtml nut instead of the value I get the system reference.
System.Data.Entity.DynamicProxies.ReferralICD10Code_F7D1453817B346998A38AA8F0A6458AB31F1C8E815585BE8E92F6BBA57298BC8
The icollection is defined as
[Display(Name = "Referral ICD10Codes")]
public virtual ICollection<ReferralICD10Code> ReferralICD10Codes { get; set; }
And when I try to build up the variable to display in the cshtml I am using
#{
var reficd10codes = "";
foreach (var item in Model.Visit.ReferralICD10Codes)
{
reficd10codes = reficd10codes + " " + Model.Visit.ReferralICD10Codes.FirstOrDefault().ToString();
}
}
If I leave out the firstordefault() I get
System.Collections.Generic.HashSet`1[Clinton.Core.Domain.ReferralICD10Code]
So now I am trying to figure out how to get the actual values instead of the reference.
Thanks

Related

Adding a dynamic list of parameters with Html helper

I'd like to be able to feed in a list of parameter names and values into a Html.Actionlink but the helper doesn't create the parameters as I would like. Any ideas how to do this?
public class ParameterNameValue
{
public string ParameterName { get; set; }
public string ParameterValue { get; set; }
}
View
#foreach (var action in post.FeedActions)
{
var parameters = "";
foreach (var param in action.Parameters)
{
parameters += param.ParameterName + "=" + param.ParameterValue + ",";
}
#Html.ActionLink(#action.Label, action.ActionName,
new { controller = action.Controller, id = action.CommunityId, slug = action.Slug,
Fromfeed=true,parameters }, new { #class = action.Classes })
}
yields a link like this:
Whereas I need the parameters part to look like:
?FromFeed=true&MatchId=1234&InnerId=5678
edit: I got it working by just manually creating the tag, but no doubt there's a nice way of doing this by creating a custom helper.
#action.Label
I'd suggest you to extend the classic ActionLink helper with a prototype similar to this (add a parameter for your specific class) :
public static MvcHtmlString ActionLinkCustom(this HtmlHelper html, string linkText, string actionName, string controllerName, object routeValues, List<ParameterNameValue> yourOtherValues)
In the code, check if you got any custom values. If such, add them to the RouteValuesDictionnary. Then use the classic ActionLink helper providing this modified RouteValuesDictionnary.
Note : you can work on the routeValues using this
IDictionary<string, object> RouteValues = HtmlHelper.ObjectToDictionary(routeValues);

Is there in JSON function which dumps JSON array of dictionary into tab separated text files

I have an JSON array as defined below:-
[
{"Name":"Ayush","Age":24,"Job":"Developer"},
{"Name":"Monika","Age":23,"Job":"Developer"},
{"Name":"Chinmay","Age":23,"Job":"Developer"}
]
I want to dump this into text file in following format:-
Name Age Job
Ayush 24 Developer
Monika 23 Developer
Chinmay 23 Developer
Is there any C# function to accomplish the above? If not, how can i achieve it with minimum memory consumption?
Thanks in advance
There is no such built-in function. You may achieve this by reading JTokens from input stream using JsonTextReader and writing their values into another stream. Stream input and output ensures minimal memory footprint.
using (var inputStream = File.OpenRead("input.json"))
using (var streamReader = new StreamReader(inputStream))
using (var jsonTextReader = new JsonTextReader(streamReader))
using (var outputStream = File.OpenWrite("output.csv"))
using (var streamWriter = new StreamWriter(outputStream))
{
var firstItem = true;
while (jsonTextReader.Read())
{
if (jsonTextReader.TokenType == JsonToken.StartObject)
{
var jObject = JObject.ReadFrom(jsonTextReader);
if (firstItem)
{
streamWriter.WriteLine(string.Join("\t",
jObject.Children().Select(c => (c as JProperty).Name)));
firstItem = false;
}
streamWriter.WriteLine(string.Join("\t",
jObject.Values().Select(t => t.ToString())));
}
}
}
Demo: https://dotnetfiddle.net/2fCRa6. (I used MemoryStream and Console instead of input and output file streams in this demo since .NET Fiddle does not allow file IO, but the idea is the same.)
You can create a class with Name, Age and Job as properties.
public class Info{
public string Name { get; set; }
public int Age { get; set; }
public string Job { get; set; }
}
Then in another function use we can use System.Web.Script.Serialization class(to use this class make sure you have referenced System.Web.Extensions in project references). Once done we can use JavaScriptSerializer class and get list of objects from the json data. Then we can iterate over each item and add it two our file with a tab as a delimeter.
public static void WriteDetailsInFile(string jsonData)
{
var list = new JavaScriptSerializer().Deserialize<List<Info>>(jsonData);
using (var streamWriter = File.AppendText("D:MyFile.txt"))
{
streamWriter.WriteLine("Name\tAge\tJob");
foreach (var item in list)
{
streamWriter.WriteLine(item.Name + "\t" + item.Age + "\t" + item.Job);
}
}
}
//driver
public static void Main()
{
string data = #"[
{ ""Name"":""Ayush"",""Age"":24,""Job"":""Developer""},
{ ""Name"":""Monika"",""Age"":23,""Job"":""Developer""},
{ ""Name"":""Chinmay"",""Age"":23,""Job"":""Developer""}
]";
WriteDetailsInFile(data);
}

Convert string to html attributes

Is their a way to convert a string (this string can change and contains asp-route-... attributes) to a list of html attributes? The razor engine should use all the asp-route-... attributes to convert to a correct url. I have the following code but that doesn't work.
#{
var Attributes = ViewData["Attributes"] as Dictionary<string,string>;
var AttributeRoute = "";
#foreach (var key in Attributes.Keys)
{
AttributeRoute += "asp-route-"+key+"=\""+Attributes[key]+"\" ";
}
}
...
#AttributeRoute #Prints output (ex. asp-route-testkey="testvalue")
<a class='item' #AttributeRoute>test</a> #Doesn't print the list of attributes
Solved it myself by doing the following:
1. Create custom Taghelper class
namespace test
{
[HtmlTargetElement("special-link")]
public class SpecialLinkTagHelper : TagHelper
{
[ViewContext]
public ViewContext ViewContext { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
//Create a tag
output.TagName="a";
//Get the parameters
string parameters="";
Dictionary<string,string> Parameters = (Dictionary<string,string>)this.ViewContext.ViewData["Attributes"];
foreach(KeyValuePair<string, string> pair in Parameters){
parameters+= pair.Key+"="+pair.Value+"&";
}
output.Attributes.SetAttribute("href", "?"+parameters);
}
}
}
2. Create Link (in a .cshtml file)
<special-link>link</special-link>
Hope this can help someone!

Get scaffolder to generate fields in specific order

I am trying to get asp.net core MVC to scaffold a Razor View with fields in a different order than the apparently default alphabetical order. I've got a simple model:
public class Application : EntityBase
{
[Display(Name = "Naam", Order = 1)]
public string Name { get; set; }
[Display(Name = "Omschrijving", Order = 2)]
public string Description { get; set; }
}
I want the scaffolder to generate a field for Name before Description. How to do this?
I've been trying to come up with a solution in the Razor template. The relevant code is:
...
IEnumerable<PropertyMetadata> properties = Model.ModelMetadata.Properties;
foreach (var property in properties)
{
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
{
...
I was hoping that a property had an Order-property, so I could write something like
foreach (var property in properties.OrderBy(p => p.Order))
Any ideas?
So, after some (deep) digging I came up with a solution. As I allready customized the templates, it was acceptable to add yet another customization. I ended up creating a helper class ScaffoldHelpers.cs:
public class ScaffoldHelpers
{
public static IEnumerable<PropertyMetadata> GetPropertiesInDisplayOrder(string typename, IEnumerable<PropertyMetadata> properties)
{
Type type = Type.GetType($"{typename}, {typename.Split('.')[0]}");
SortedList<string, PropertyMetadata> propertiesList = new SortedList<string, PropertyMetadata>();
foreach (PropertyMetadata property in properties)
{
int order = 0;
if (type != null)
{
var member = type.GetMember(property.PropertyName)[0];
var displayAttribute = member.GetCustomAttribute<System.ComponentModel.DataAnnotations.DisplayAttribute>();
if (displayAttribute != null)
{
order = displayAttribute.Order;
}
}
propertiesList.Add($"{order:000} - {property.PropertyName}", property);
}
return propertiesList.Values.AsEnumerable();
}
}
This iterates over all the properties, and determines if a [Display()] attribute is specified. If so, it gets the value of the Order-parameter. If you don't specify this, the Order-property will be zero. Using a SortedList and making sure the key is ordered by the specified order, I'm able to easily return an IEnumerable<PropertyMetadata> in the desired order.
In the template, I needed to add #using for this helper-class. After that, I could insert the following into the template:
...
IEnumerable<PropertyMetadata> properties = Model.ModelMetadata.Properties;
// added:
properties = ScaffoldHelpers.GetPropertiesInDisplayOrder(Model.ViewDataTypeName, properties);
foreach (var property in properties)
{
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
{
...
That's it!

Iterating though items of Model in MVC 4

I would like to iterate though the item returned from the foreach(var item in Model). Like for(int i=0; i <item.length; i++) and then subsequently write the individual html code for the items returned by the model.
Unfortunately, I cannot seem to be able to access item.length as the property doesn't exists. Would anyone know how I could iterate through each model item so that I could save up on writing a lot of unnecessary HTML?
So some more context in lieu of the question being unclear:
Let's say my model is
public class RegisterViewModel
{
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
Now I use a DB call to access the model data and parse it to the view via
RegisterViewModel model= db.RegisterViewModel.Where(data => data.Name == User.Name);
Now I pass this model to the view via view(model)
Now to display data for all the students, I can use a
model IEnumerable<Project.Models.RegisterViewModel>
#foreach(item in Model) {
#for(int i=0; i<item.Length;i++) { \\this is where I would like to iterate though the item
if(item[i]!= null) // using a for loop would avoid me having to write this if condition multiple times.
<div>#item[i].value</div>
}
}
You cannot iterate over item because item is of type RegisterViewModel. It doesn't make sense to be doing this.
If you want to display the value you could directly use it like this:
#model IEnumerable<Project.Models.RegisterViewModel>
#foreach(item in Model) {
<div>#item.Value</div>
}
Also bear in mind that the following line of code in your controller is wrong:
RegisterViewModel model = db.RegisterViewModel.Where(data => data.Name == User.Name);
The .Where extension method returns an IEnumerable<T> so you'd rather have:
IEnumerable<RegisterViewModel> model = db.RegisterViewModel.Where(data => data.Name == User.Name);
return View(model);
or if you prefer:
var model = db.RegisterViewModel.Where(data => data.Name == User.Name);
return View(model);