There's a property Path on JToken.
But it escapes the name of object with "[' ']" if the object name contains a "."
XPATH : dir/nested_dir/file.txt
JSON: dir.nested_dir.['file.txt']
Is there some other property that will return the path as an array of string ?
As pointed out here: https://stackoverflow.com/a/19727164/1555435
Use brackets and quotes around your field. For example, if your field is valid.key.with.dot
Refer to it as ['valid.key.with.dot'] and in JsonPath, try
JsonPath.read(jsonString, "$.['valid.key.with.dot']")
Check out this dotNetFiddle
There is not a built-in property that does this, but you can make an extension method that does what you want easily enough:
public static class JsonExtensions
{
public static string[] PathAsArray (this JToken token)
{
return token.AncestorsAndSelf()
.OfType<JProperty>()
.Select(p => p.Name)
.Reverse()
.ToArray();
}
}
Then use it like this:
var pathArray = token.PathAsArray();
Console.WriteLine(string.Join("/", pathArray));
Fiddle: https://dotnetfiddle.net/GOdo7t
Note: the above extension method ignores any JArrays that might be in the path. You will need to make adjustments to the code if you need to handle arrays.
Related
Maybe a stupid question. C# 6.0 allows for string replacement using this syntax: $"string content {foo} {bar}". I would like to imitate this behavior in a class I've written for strings passed to it by default. The problem is that I am not sure how to access the public properties/variables. I am not sure if there is a way to access the properties using reflection or by passing this or this.Page to the constructor.
Figured it out:
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
object UID = GetPropValue(System.Web.HttpContext.Current.Handler, "UID");
I'm using the new bolt compiler (introduced here: https://www.firebase.com/blog/2015-11-09-introducing-the-bolt-compiler.html)
I have the need to define an index on the owner field of my type Event:
type Event {
description : String | Null,
name : String,
color : Number,
owner : String,
shared : Boolean
index() = "owner";
}
When I try to compile this code, I get the following output:
bolt: Generating rules.json...
bolt:1:1: Unsupported method name in type statement: 'index' (allowed: 'validate', 'read', 'write')
Please help: how should I define indexes? I guess I need to define them within a path statement?
The documentation for the bolt compiler does not contain much on defining indexes yet: https://github.com/firebase/bolt/blob/master/docs/language.md
Just found the answer:
path /users/$uid/events {
index() = "owner";
}
Combining the type info with the index:
path /events is Event[] {
index() = "owner";
}
I've created a small test class, that returns data from an xml file.
I now want to make it more dynamic using linq but cannot get it to work.
public class LenderCollection
{
string fileName = "C:\\Lenders.xml";
public IEnumerable<Lender> Lenders { get; set; }
public void FetchLenders(Expression<Func<Lender, bool>> predicate = null)
{
IEnumerable<Lender> lenders = XmlHelper.GetObjectFromXml<List<Lender>>(fileName, "AllLenders");
Lenders = predicate.IsNotNull() ? lenders.Where(predicate) : lenders;
}
}
Visual Studio is giving an error on the section "lenders.Where(predicate)" - the message is "... does not contain a definition for Where..."
Any ideas what I'm doing wrong?
* UPDATE *
It seems to be something to do with the predicate - .Where is avaialable otherwise.
There's no extension method Where that extends IEnumerable<T> and takes a parameter of type Expression<Func<T, bool>>.
You have two options:
Use an IQueryable<Lender> instead of IEnumerable<Lender> (you can this easily by just calling .AsQueryable()) if you wan to keep the parameter predicate as Expression<Func<Lender, bool>>
Use the type Func<Lender, bool> instead of Expression<Func<Lender, bool>> for the predicate parameter. Since you're loading your data from a file, there's no point in using an IQueryable over an IEnumerable.
It's complaining that whatever type lenders is does not have a .Where method. This is either because:
You haven't included using System.Linq;
The type of lenders isn't an IEnumerable or similar.
Replace:
lenders.Where(predicate)
With:
lenders.ToList().Where(predicate)
Both should be able to return IEnumerable.
The main downfall with this is that the query will execute on the .ToList() command. I guess this is down to what you expect your function to be doing though, and if this is acceptable for your needs.
Imagine a simple controller action IEnumerable<BaseType> Get(). It returns an enumeration of different types all deriving from BaseType.
When the client requests XML, the result is something like this:
<ArrayOfBaseType>
<BaseType i:type="DerivedType1"><A>value</A></BaseType>
<BaseType i:type="DerivedType2"><B>value</B></BaseType>
<BaseType i:type="DerivedType3"><C>value</C></BaseType>
</ArrayOfBaseType>
As you can see, the type of the derived class is transmitted in the i:type attribute.
If the client requests JSON however, this information is missing:
[
{"A":"value"},
{"B":"value"},
{"C":"value"}
]
How to fix this?
The following change is necessary:
In the WebApiConfig.cs the following line needs to be added:
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling =
TypeNameHandling.Auto;
This will automatically result in a new property $type when needed.
If you write your class following:
public class MyClass
{
// properties here
public string IType
{
get
{
return this.GetType().Name;
}
set { }
}
}
Maybe, it will help you
What is the simplest way of adding a selected css class to an ActionLink if the url of the action link matches the page being displayed?
Thanks!
This might do the trick
var currentUrl = location.pathname; //spits out something like 'Home/About'
$('a').each(function() {
if ($(this).attr('href') == currentUrl) {
$(this).addClass('yourClassName');
}
});
This is a hard question, at first glance the only valid answer that comes to my minds is "it depends". Do you mean simple as in simple to code or simple to understand or simple to...
It can be done using jquery and window.location.pathname stripping out and applying class based on controller and/or action (usually .substr(1 and/or 2)).
It can be done using MenuModel with SelectedItem pointer, adding class based on it.
It can be done using MenuItem[] with property selected, adding class based on it.
It can probably be done in various additional ways (ViewBag springs to mind).
Each consisting of two steps:
1. Save/calculate selected menu item
2. Set class based on this.
As for what is more simple, I think it depends on your preferences and the requirements on the site. The javascript approach might not be the best if you are to support non-javascript users ^^
Rant out
We match the current URL against a regex for each nav option and set it selected if there is a match.
add a property like LinkCssNaame to your view model and have the controller set it on the server
You can use this extension method.
public static MvcHtmlString ActionLinkWithSelection(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName)
{
const string action = "action";
const string controller = "controller";
const string selected = "selected";
var routeValues = htmlHelper.ViewContext.RouteData.Values;
var linkMatchesRoute = routeValues.ContainsKey(action) && routeValues.ContainsKey(controller) &&
actionName.Equals(routeValues[action]) && controllerName.Equals(routeValues[controller]);
return htmlHelper.ActionLink(linkText, actionName, controllerName, null, linkMatchesRoute ? new { #class = selected } : null);
}