Use Content instead of Document in Umbraco (v6) - umbraco

I would like to update some obsolete code from umbraco v4 in the updated to v6 solution.
I have
entitiesFolder = new umbraco.cms.businesslogic.web.Document(folderId);
entitiesFolder.ReorderChildren(
entitiesFolder.Children.OrderBy(fdoc => fdoc.Text),
refreshEntireCache);
Now the recomendation instead of obsolete Document is to use Umbraco.Core.Models.Content. How? Didn't find (as usual for Umbraco) any documentation about... (
// new version
var toto = new Umbraco.Core.Models.Content(??)
toto.SoirtChildren(???)

Are you doing this from a razor view? If so you can do:
var nodeId = 123;
var myNode = Umbraco.TypedContent(nodeId);
var property = myNode.GetPropertyValue<string>("myStringAlias");
If you're doing it from a class or something you'll have to use something like:
var helper = new UmbracoHelper(UmbracoContext.Current);
var nodeId = 123;
var myNode = helper.TypedContent(nodeId);
(This is untested but it should work..)

If you are just querying data and need to sort it, using the umbracoHelper is a great way to go. It only hits the xml cache in App_Data/umbraco.config, so you don't hit the database.
However, if you are attempting to programatically sort some of the nodes in the content tree, you will need to use the ContentService. You will need to use the ContentService whenever you actually want to programatically modify content nodes. You will also find a similar MediaService for media.
https://our.umbraco.org/Documentation/Reference/Management-v6/Services/ContentService
ApplicationContext.Current.Services.ContentService.Sort(...)

Related

How do I set the `search` URL parameter in SAPUI5 OData requests?

I want my SAPUI5 ODataModel to send OData requests of the form
https://<my-server>/<my-service>/<my-resource>?search='lalaland'
There are tons of examples how to add a filter with model.filter(new Filter(...)); but this is not what I want. Filtering means I directly address a certain property with a certain comparator. Searching means I address the resource in general and let the OData service decide which properties to search, and how.
The one thing that seems to be possible is:
model.bindRows(..., { "customData": {"search": "lalaland"}});
But this is also not what I want because that sets the search term once when the model is created, but cannot update it later on when the user enters.
Funnily, SAPUI5's own implementation of the SmartTable performs exactly the kind of query I want - but doesn't reveal a possibility how I could do that without a SmartTable.
Found one solution:
oList = this.byId("list"); // or oTable
oBindingInfo = oList.getBindingInfo("items"); // or "rows"
if (!oBindingInfo.parameters) {
oBindingInfo.parameters = {};
}
if (!oBindingInfo.parameters.custom) {
oBindingInfo.parameters.custom = {};
}
oBindingInfo.parameters.custom.search = sValue;
oList.bindItems(oBindingInfo);
However, I don't specifically like the bindItems part. Looks a bit over-the-top to require this to re-bind the whole entity set again and again. So leaving this question open in case somebody has a better idea.
You can use on bindItems or bindRows depending what control is, something like this:
oList = this.byId("list");
oList.bindItems({path: '/XXXX', parameters : {custom: {'search':'searchstring'}}})
Why does it has to be $search and not $filter?
The OData V4 Tutorial in SAPUI5's Demo Kit uses
onSearch : function () {
var oView = this.getView(),
sValue = oView.byId("searchField").getValue(),
oFilter = new Filter("LastName", FilterOperator.Contains, sValue);
oView.byId("peopleList").getBinding("items").filter(oFilter, FilterType.Application);
},

Audit Log to Maintain History Against Records using Repository Pattern.

I want to implement audit log against each single record, so its looks like an history for records so user can view what operation perform against it,what is previous value? what is current value? like this, using a Repository pattern in MVC.
Someone please help me.
Thank you.
Disclaimer: I'm the owner of the project EF+ (EntityFramework Plus)
You can use EF+ Audit which allow to easily track changes, exclude/include entity or property and auto save audit entries in the database.
// using Z.EntityFramework.Plus; // Don't forget to include this.
var ctx = new EntityContext();
// ... ctx changes ...
var audit = new Audit();
audit.CreatedBy = "ZZZ Projects"; // Optional
ctx.SaveChanges(audit);
// Access to all auditing information
var entries = audit.Entries;
foreach(var entry in entries)
{
foreach(var property in entry.Properties)
{
}
}
Project: http://entityframework-plus.net/
Documentation: http://entityframework-plus.net/audit

Umbraco: Update Property on specific member

I'm running a forum with Umbraco 7, and I wish to update a property on a specific member by hes Id.
This is what I tried:
var authorId = Model.Content.GetPropertyValue<int>("postAuthor", 0);
var author = Members.GetById(authorId);
umbraco.cms.businesslogic.member.Member member = umbraco.cms.businesslogic.member.Member.GetMemberFromEmail(author.GetPropertyValue("email").ToString());
member.getProperty("postCounter").Value = Convert.ToInt32(member.getProperty("postCounter")) + 1;
member.Save();
But this dont work and the line below throws this error:
umbraco.cms.businesslogic.member.Member member = umbraco.cms.businesslogic.member.Member.GetMemberFromEmail(author.GetPropertyValue("email").ToString());
It says: Warning: umbraco.cms.businesslogic.member.Member is obsolete: "Use the MemberService and the Umbraco.Core.Models.Member models instead"
Can someone help me solve this?
var memberService = ApplicationContext.Current.Services.MemberService
var member = memberService.GetById(authorId)
member.SetValue("postCounter", newValue);
memberService.Save(member);
Never, ever do this though!!
You need to store counts like this that update really frequently in your own separate table as each time you save a piece of content (and yes, the member object is basically a piece of content as well) you will save a new version in the versions table. All of your custom properties will also be saved again with the new version. Also this is a fairly database-intense operation which is completely unnecessary, just have a table with two columns: the memberId and the count and you're done and it's all very lean and performant.
If you are in razor script you want to do something like:
var authorId = Model.Content.GetPropertyValue<int>("postAuthor", 0);
var ms = ApplicationContext.Current.Services.MemberService;
var member = ms.GetById(authorId);
member.SetValue("postCounter",member.GetValue("postCounter"));
But as sebastian says you probably want to do it differently for performance

How can I get children of a node?

How can I get all the children for the News item (in the standard project) in a partialview (razor)?
I've tried:
#{
var homePage = CurrentPage.AncestorsOrSelf(1).First();
var newsItems = homePage.Children.Where(x => x.GetProperty("Name").Value == "News");
}
But I get an error that states I can't do lambda expression, whitout casting it. "News" is a node in my webpage holding children and I want to create a macro listing the children. How and what can I cast it to?
Currently, you are looking for children of the home page, named "News". I think you want to go one level deeper.
I reccomend this approach:
// 1- Get root node
var site = Model.Content.AncestorOrSelf("Site");
// 2- Get news node
var news = site.Descendant("News");
var newsItems = news.Children;
Here you use the document type alias to traverse your tree, this is much more reliable than using names, as those can change. This of course may require to rework some elements.
Hope this helps!
Try this to get all of the news nodes that are children of homepage:
var newsItems = homePage.Children.Where("Name = #0", "News");
Then iterate through the children of News:
foreach (var newsChild in newsItems)
You could skip the first step if you already know the ID of your news node like so:
var newsNode = Umbraco.Content(1234);
This page has plenty of examples:
http://our.umbraco.org/documentation/reference/querying/DynamicNode/Collections#

How to get the Layout value of razor files?

I'm doing some custom infrastructure for auto-generating specific bundles for individual views, and have a case where I need to get the Layout value for each view while iterating them as files.
I've tried var view = new RazorView(new ControllerContext(), actionView.FullName, null, true, null); but this is taking the LayoutPath as an input, and it is indeed resulting in an empty string on the LayoutPath property of the RazorView if I give null for that parameter, so it's not parsing the file for the value.
Could there be any other way to solve this in a similar manner, or would my best/only option be to just parse the text of the raw file (and _ViewStart)?
This is only done once at application start, so the performance is currently not an issue.
Alright, after a lot of source debugging and an epic battle with the internal access modifier, I have a working solution without having to render the whole page. I don't expect anyone else ever having the need for this, but anyway:
var httpContext = new HttpContextWrapper(new HttpContext(new HttpRequest("", "http://dummyurl", ""), new HttpResponse(new StreamWriter(new MemoryStream()))));
var page = Activator.CreateInstance(BuildManager.GetCompiledType(ReverseMapPath(actionView.FullName))) as WebViewPage;
page.Context = httpContext;
page.PushContext(new WebPageContext(), new StreamWriter(new MemoryStream()));
page.Execute();
var layoutFileFullName = page.Layout;
// If page does not have a Layout defined, search for _ViewStart
if (string.IsNullOrEmpty(layoutFileFullName))
{
page.VirtualPath = ReverseMapPath(actionView.FullName);
var startpage = StartPage.GetStartPage(page, "_ViewStart", new string[] {"cshtml"});
startpage.Execute();
layoutFileFullName = startpage.Layout;
}
Tada!
Ps. ReverseMapPath is a any arbitrary function to resolve the relative path of a full file name, see for example Getting relative virtual path from physical path

Resources