Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Frans de Jong 548 posts 1840 karma points MVP 3x c-trib
    Nov 17, 2016 @ 09:50
    Frans de Jong
    0

    The quest for strongly typed member properties

    Hi to all,

    Is isn't a real question but more a attempt to try and make a piece of code for everybody to use. But than again maybe someone solved this issue before.

    The problem: We ran into this problem in multiple projects already but the latest project where we encountered this problem is in a intranet.

    In this intranet there are up to 500 members. For now they all have about 35 properties. I want the properties available as strongly typed properties preferably using the model rendered by models-builder. If I would add a property it would instantly be available.

    Example On the homepage I'm showing a range of birthdates, a few days back and a few days forward.

    I get all the members :

    IEnumerable<IMember> members = Services.MemberService.GetAllMembers();
    

    What I want to do next is get 3 properties in a custom viewmodel.

    HomeBirthdateModel homeBirthdateModel = new HomeBirthdateModel();
    
                homeBirthdateModel.birthdayPast = members.Where(x => ((x.DateOfBirth > minDate) && (x.DateOfBirth < today)));
                homeBirthdateModel.birthdayToday = members.Where(x => (x.DateOfBirth == today));
                homeBirthdateModel.birthdayFuture = members.Where(x => ((x.DateOfBirth > today) && (x.DateOfBirth < maxDate)));
    

    This is not going to hapen becouse I'm not dealing with the Umbraco.Web.PublishedContentModels.Member but with the Umbraco.Core.Models.Member

    The solution? I'd like to make a controller with a method IMemberToMember() that gets a List<IMember> and returns a List<member>. The Ideal way would be looping through the properties of the IMember and matching the name of the property with the Member. This way I can always call this method and don't care about the current properties.

    The first problem I ran in to is the Member.generated.cs has a constructor in it depending on IPublishedContent.

    public Member(IPublishedContent content)
                : base(content)
            { }
    

    Who has ran into this problem before and is willing to work to a solution with me. The goal is to be able to use strongly typed properties preferably using the generated models. I could always fall back to a custom model but it seems more logic to use the already generated model.

    Thanks for reading this long post! :P

    Frans

  • Frans de Jong 548 posts 1840 karma points MVP 3x c-trib
    Nov 17, 2016 @ 13:39
    Frans de Jong
    0

    As usual, when I start asking questions I'll find the solution very soon...

    If you get all the members via the memberservice you'll get the IContent and not the IPublishedContent...

    So If you want a list with all members with the strongy typed model from modelsbuilder this is the (a?) way.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using Umbraco.Core.Models;
    using Umbraco.Web.Mvc;
    using Umbraco_SiouxIntranet.Models.ServiceApi;
    using PublishedMember = Umbraco.Web.PublishedContentModels.Member;
    
    namespace Umbraco_SiouxIntranet.Controllers.ServiceApi
    {
        public class ServiceApiController : SurfaceController
        {
            [HttpGet]
            public ActionResult GetMemberBirthDays()
            {
                DateTime minDate = today.AddDays(-5);
                DateTime maxDate = today.AddDays(5);
                IEnumerable<IMember> members = Services.MemberService.GetAllMembers();
                List<PublishedMember> publishedMembers = new List<PublishedMember>();
                foreach (IMember iMember in members)
                {
                    PublishedMember publishedMember = new PublishedMember(Umbraco.TypedMember(iMember.Id));
                    publishedMembers.Add(publishedMember);
                }
    
                HomeBirthdateModel homeBirthdateModel = new HomeBirthdateModel();
    
                homeBirthdateModel.birthdayPast = publishedMembers.Where(x => ((x.DateOfBirth > minDate) && (x.DateOfBirth < today))).ToList();
                homeBirthdateModel.birthdayToday = publishedMembers.Where(x => (x.DateOfBirth == today)).ToList();
                homeBirthdateModel.birthdayFuture = publishedMembers.Where(x => ((x.DateOfBirth > today) && (x.DateOfBirth < maxDate))).ToList();
    
                return View("ServiceApi/HomeBirthDays", homeBirthdateModel);
            }
        }
    }
    

    Now I only have to fix the date comparisson. Life can be so easy :P

  • Sebastiaan Janssen 5045 posts 15476 karma points MVP admin hq
    Nov 18, 2016 @ 10:24
    Sebastiaan Janssen
    100

    However: Services.MemberService.GetAllMembers() is a very naughty thing to do! And it doesn't scale. This will execute 1 or more queries to the database for each member in the database (can't remember exactly how this works).

    Instead you should be the MembershipHelper which returns (hey, look at that, just what you were looking for!): IPublishedContent. :-)

    The catch, however, is that there's no way to get all members. If you absolutely must get them all then I would recommend you do a quick database query to find the ids of all members (I think it's something like SELECT id FROM umbracoNode WHERE nodeObjectType = '39EB0F98-B348-42A1-8662-E7EB18487560' - I got the object type from here). Make sure to cache the results of this query if this page is going to be loaded a lot.

  • Frans de Jong 548 posts 1840 karma points MVP 3x c-trib
    Nov 18, 2016 @ 12:29
    Frans de Jong
    0

    Hi Sebastiaan,

    The problem is indeed that I do need all the members. I'll look into the direct database query you mentioned. This is for a internet with up to 500 members so I'm not that worried about the caching part.

    Thanks !!

  • Frans de Jong 548 posts 1840 karma points MVP 3x c-trib
    Dec 05, 2016 @ 16:16
    Frans de Jong
    0

    Is this the way you would do the query?

    Guid memberObjectTypeGuid = new Guid("39EB0F98-B348-42A1-8662-E7EB18487560");
                var db = ApplicationContext.Current.DatabaseContext.Database;
                IEnumerable<int> listOfMemberIds = db.Query<int>("SELECT id FROM umbracoNode WHERE nodeObjectType=@0", memberObjectTypeGuid);
    
  • Frans de Jong 548 posts 1840 karma points MVP 3x c-trib
    Dec 14, 2016 @ 08:49
    Frans de Jong
    0

    For the overview we moved to the indexer to get the list we need. This gives us a lot more speed and has the added benefits of filtering capabilities. The fields contain the data we need so we can use those for displaying name and so on.

Please Sign in or register to post replies

Write your reply to:

Draft