How does umbraco.cms.businesslogic.template.Template.Import work? - umbraco

Does anyone happen to know how
umbraco.cms.businesslogic.template.Template Import(System.Xml.XmlNode n, umbraco.BusinessLogic.User u)
in the Umbraco API works? More specifically what the XMLNode you're supposed to pass in looks like (is supposed to be)? I've been searching for a reference on this method for a while now, can't seem to find anything. The API reference on the Umbraco wiki isn't helping much either.

To answer my own question, here is the source code for the function:
public static Template Import(XmlNode n, User u)
{
string alias = xmlHelper.GetNodeValue(n.SelectSingleNode("Alias"));
Template t = Template.GetByAlias(alias);
if (t == null)
{
t = MakeNew(xmlHelper.GetNodeValue(n.SelectSingleNode("Name")), u);
}
t.Alias = alias;
t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design")));
return t;
}

Related

How to get my object (Generator) from a Map<UUID, List<Generator>> with streams?

I've been wanting to check the location of my Generator and use streams to check if the location is valid.
The idea was as follows;
public Generator getGeneratorFromLocation(final Location location) {
for (List<Generator> generator : playerGeneratorMap.values()) {
for (Generator generator1 : generator) {
if (generator1.getGenLocation().equals(location)) {
return generator1;
}
}
}
return null;
}
I'm wanting to return a Generator from this using streams instead to try and learn more ways of doing it.
Current map:
public final Map<UUID, List<Generator>> playerGeneratorMap = new HashMap<>();
Any help would be greatly appreciated.
You can use AtomicRef object to init a retVal and then assign the wanted Generator to it in the lambda expression because regular vars can't be assigned in lambdas, only final or effectivly final can be used inside arrow functions.
This function should solve the problem :)
public Generator getGeneratorFromLocation(final Location location) {
AtomicReference<Generator> retVal = new AtomicReference<>(null);
playerGeneratorMap.values().stream().forEach(generators -> {
generators.forEach(generator -> {
if (generator.getLocation().equals(location)) {
retVal.set(generator);
}
});
});
return retVal.get();
}
By the way, streams are unnecessary because you have Collection.forEach instead of Stream.forEach, streams are used for more 'exotic' types of iterations like, filter, anyMatch, allMatch, reduce and such functionalities, you can read about Streams API on Oracle's website,
I'll link in the docs for you for future usage, important for functional proggraming.

Swashbuckle custom string comparer not applied for order groups of actions

In Swashbuckle there is a setting called OrderActionGroupsBy which is supposed to change the ordering within the API, but nothing I do is working and I'm can't determine whether this is a Swashbuckle problem, or due to my IComparer any idea what I'm doing wrong?
This is setting the configurations
config.EnableSwagger(c =>
{
...
c.OrderActionGroupsBy(new CustomStringComparer());
c.GroupActionsBy(apiDesc => GroupBy(apiDesc));
...
}
This is grouping the actions by type instead of controllerName.
private static string GroupBy(ApiDescription apiDesc)
{
var controllerName = apiDesc.ActionDescriptor.ControllerDescriptor.ControllerName;
var path = apiDesc.RelativePath;
if (controllerName.Contains("Original"))
{
controllerName = controllerName.Replace("Original", "");
}
// Check if it is one of the entities if so group by that
// Otherwise group by controller
var entities = new List<string>() { "Users", "Apps", "Groups" };
var e = entities.Where(x => attr.Contains(x.ToLower())).FirstOrDefault();
if (e != null)
{
return e;
}
return controllerName;
}
This is my attempt at an IComparer I want Users first and then after that alphabetical
class CustomStringComparer : IComparer<string>
{
public int Compare(string x, string y)
{
if (x.CompareTo(y) == 0)
return 0;
if (x.CompareTo("Users") == 0)
return -1;
if (y.CompareTo("Users") == 0)
return 1;
return x.CompareTo(y);
}
}
}
This isn't working it always defaults to alphabetical no matter what I do.
Looks like this is a bug with Swashbuckle/Swagger-ui
Using OrderActionGroupsBy is correctly sorting the JSON file, but then swagger ui automatically resorts this to alphabetical order.
I have filed bugs with both Swashbuckle and swagger-ui since this seems to go against what is said in swagger-ui's doc regarding apisSorter.
Apply a sort to the API/tags list. It can be 'alpha' (sort by name) or
a function (see Array.prototype.sort() to know how sort function
works). Default is the order returned by the server unchanged.
Swashbuckle issue
swagger-ui issue
swagger-ui specific stackoverflow question

Linq Generic OrderBy selector

I am using the repository pattern in a asp.net mvc application (v3) and EntityFramework (v4).
I would like to add to the repository paging functionality. I have the following sample code:
public PagedResult<T> GetPaged(int offset = 0, int limit = PagedResult<T>.NoLimit, Expression<Func<T, bool>> predicate = null)
{
var res = BaseQ.Where(_predicate);//.Skip(offset);
if (predicate != null)
res = res.Where(predicate);
res = res.Skip(offset);
if (limit != PagedResult<T>.NoLimit)
{
res = res.Take(limit);
}
return new PagedResult<T>(res, res.Count(), offset, limit);
}
However, this will not work because Entity framework throws an exception that I should call OrderBy before Skip.
I am wondering how can I implement this in a generic way so that the order by expression will be plugged in from the outside. I would then pass it as a parameter.
Perhaps there is also another way of working around that problem.
[EDIT] I found out that this can be done by passing in the name of the property and creating an expression out of that, but I would like to actually just use it as I am using it in the OrderBy. So just pass in (c=>c.ID) for example.
Thanks in advance for any ideas
I have decided to go with passing in a string and creating the expression from it

pass parameter to repository while maintaining separation of concerns

I'm new to mvc and this whole way of programming is pretty unfamiliar for me, so be gentle ...
I have in my article repository:
public IQueryable<Article> GetArticles(int? category, int? position)
{
return from a in dc.Articles
where a.LanguageIndex == lang && a.CategoryIndex == category && a.ArticlePosition == position
select a;
}
How can I pass the parameters category and position from the interface while maitaining separation of concerns ?
I thought about :
public interface IArticleRepository
{
IQueryable<Article> GetArticles(Article a);
}
and passing the parameters along with the Article object, but this means I would have to pass the category and position in the controller.
Am I in the right direction here?
Not sure how this relates to separation of concerns. I can see where it might seem the abstraction is leaky; is it your concern that it seems users must know a little too much about how the repository holds your Articles?
Until someone comes up with a performant method of separating implementation from models, storage abstractions will always be leaky. You can beat yourself up over it or just do your best and deal.
Your second method is, IMHO, worse than the first. You still have to stipulate the category and position in your Article, so you still have the leak in addition to a weird API that confuses parameters with entities.
I'd definitely go with the first version over the second. If I were to do anything, I would refactor to make CategoryIndex and ArticlePosition entities (Category and Position tables linked to the Article table). You could then refactor your API to the more appealing:
var cat = CategoryRepository.GetCategory("foo");
var pos = PositionRepository.GetPosition("bar");
var article = ArticleRepository.GetArticle(cat, pos);
Is this any better than what you already have? Probably not.
Fist I would separate out the basic query:
public IQueryable<Article> GetArticles()
{
return from a in dc.Articles select a;
}
public IQueryable<Article> GetArticles(int? category, int? position)
{
return GetArticles ().Where (a => a.LanguageIndex == category && a.CategoryIndex == position).AsQueryable ();
}
Now if you want to move the specific query filter out of your repository you can move it to an extension method:
public static IQueryable<Article> WithCategory(this IQueryable<Article> articles, int? category, int? position)
{
return articles.Where (a => a.LanguageIndex == category && a.CategoryIndex == position).AsQueryable ();
}

Get Properties from Member in Umbraco programmatically

I thought this would be really simple but ..
We've create a user and a member type with various properties
When we try to access the properties via the member object we got nothing.
//Member m is current User
eg.
Property s = m.getProperty("PreferdUserName");
is null
m.getProperties has a count of Zero..
have we missed something obvious?
Could there be a spelling error?
"PreferdUserName" may want to be "PreferredUserName".
Other than that it looks correct.
In the end i resorted to storing member properties in a separate db table, which anyhow is closer to what i need.
I presume it had something to do with the way I created the memberType from outside umbraco using a custom msbuild task.
You could create your own class and extend ProfileBase. The code below will expose the properties that you have created within Umbraco. e.g. umbraco alias is 'first_name'.
[SettingsAllowAnonymous(false)]
public string FirstName
{
get
{
var o = base.GetPropertyValue("first_name");
if (o == DBNull.Value)
{
return string.Empty;
}
return (string)o;
}
set
{
base.SetPropertyValue("first_name", value);
}
}
Then you can access properties like so...
string firstName = ((MemberProfile)HttpContext.Current.Profile).FirstName;
More info about how to set this all up can be seen here:
http://www.aaron-powell.com/posts/2010-04-07-umbraco-members-profiles.html
This might help someone else, if you need to get member details for someone other than the current user in Umbraco and have their Username.
var TheirUsername = "s12345";
Member MemberFind = new Member(Convert.ToInt32(Membership.GetUser(***TheirUsername***).ProviderUserKey));
//now use this value
var NameOfUser = MemberFind.Text;
var EmailAddress = MemberFind.Email;
Try
Property s = m.getProperty("PreferdUserName").value;
If that still doesn't work, then check out this great post about member properties
http://legacy.aaron-powell.com/blog/july-2009/umbraco-member-profiles.aspx

Resources