Copied to clipboard

Flag this post as spam?

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


  • Tom Engan 430 posts 1173 karma points
    Sep 06, 2017 @ 14:07
    Tom Engan
    0

    How to get mixed text and HTML-codes from surfacecontroller to partial view?

    Instead of running business logic directly in partial view (what is not recommended in more advanced calculations), I want to loop through a database table and generate different calculations in a list mixed with text, numbers and HTML tags in a surfacecontroller. This I wish to send to partial view overall. An example what the partial view should get can be like this:

    <h4> Most visits in 2017: </ h4>
    <p> 3 visits: John Doe </ p>
    <p> 2 visits: Jane Doe </ p>
    <p> 1 visit: john smith </ p>
    

    How does the method look like mainly in a surface controller, and how is it recommended to retrieve the html tags in partial view?

  • Kevin Jump 2327 posts 14813 karma points MVP 8x c-trib
    Sep 07, 2017 @ 08:16
    Kevin Jump
    101

    Hi Tom,

    I would return a ViewModel to the partial, and then use that to render the HTML.

    View Model:

        public class VisitViewModel
        {
            public string Period { get; set; }
            public Dictionary<string, int> Visits { get; set; }
        }
    

    Controller:

        public ActionResult GetVisits()
        {
            var visitView = new VisitViewModel();
    
            /// actual code to do something....
    
            visitView.Period = "2017";
            visitView.Visits = new Dictionary<string, int>();
    
            visitView.Visits.Add("John Doe", 3);
            visitView.Visits.Add("Jane Doe", 2);
            visitView.Visits.Add("john smith", 1);
    
            return PartialView("partial/path", visitView);
    
        }
    

    and then in your partial view you can enumerate the items

    @inherits UmbracoViewPage<YourNamespace.Models.VisitViewModel>
    
    <h4>Most visits in @Model.Period</h4>
    
    @foreach(var visit in Model.Visits)
    {
        <p>@visit.Value Visits: @visit.Key</p>
    }
    

    this way the logic remains in your controller but the HTML output is all in the Razor so it's easier to change.

    you could tidy up the Dictionary a bit, so it was another object and then it might be @visit.Count Visits: @visit.Name but other than that. I think this keeps it fairly neat.

  • Tom Engan 430 posts 1173 karma points
    Sep 08, 2017 @ 08:27
    Tom Engan
    0

    Thank you very much for the solution. Dictionary is probably what I needed. Now it's only up to me to figure out the logic for the rest of the calculations.

    Dictionary works as it should when I add more lines manually, but obviously, I have to get the number of lines from a foreach loop, and I have not figured out yet. Is this where you use ToDictionary?

  • Kevin Jump 2327 posts 14813 karma points MVP 8x c-trib
    Sep 08, 2017 @ 09:26
    Kevin Jump
    0

    Hi

    you should be able to use a dictonary directly in a foreach,

    e.g

    var myDictionary = new Dictionary<string, int>();
    
    // ... add items 
    
    foreach(var item in myDictionary) 
    {
       // item is a now KeyValuePair
       // item.Key - will be a string
       // item.Value - will be an int
    }
    
  • Tom Engan 430 posts 1173 karma points
    Sep 08, 2017 @ 09:34
    Tom Engan
    0

    What is meant by // ... add items here?

    The foreach loop is the lookup from a database table that is still growing

    foreach (HikingDestinationViewModel hikingDestination in allHikingDestinations)
    {
        //   Codes
    }
    
  • Kevin Jump 2327 posts 14813 karma points MVP 8x c-trib
    Sep 08, 2017 @ 09:54
    Kevin Jump
    0

    sorry that was just an example of the loop.

    if you are passing the dictionary back from the Controller (like the post below) then it should look like this in the razor:

    @foreach(var item in Model.Visits)  
    {
        // item.Key will be the name 
        // item.Value will be the points
    }
    

    because your dictionary is Model.Visits ?

  • Tom Engan 430 posts 1173 karma points
    Sep 08, 2017 @ 14:28
    Tom Engan
    0

    I get all my hiking destination data from this database table:

    IEnumerable<HikingDestinationViewModel> allHikingDestinations = HikingDestinations.GetAll();
    

    This is from the repository where the data in HikingDestinations above are selected:

    public static IList<HikingDestinationViewModel> GetAll()
    {
        UmbracoDatabase db = Umbraco.Core.ApplicationContext.Current.DatabaseContext.Database;
        return db.Fetch<HikingDestinationViewModel>("SELECT * FROM HikingDestinations ORDER BY StartDate");
    }
    

    and this from the foreach loop in the surfacecontroller:

    HikingDestinationViewModel model = new HikingDestinationViewModel();
    model.Visits = new Dictionary<string, int>();
    int points = 0;
    foreach (HikingDestinationViewModel hikingDestination in allHikingDestinations)
    {
        //Some untested calculations here
        //model.Visits.Add("John Doe", 1)  <<= not working when looping more than 1 time
    }
    //model.Visits.Add("John Doe", 1)  <<= working, but manual assignment can't be used
    

    And my model HikingDestinationViewModel is where public Dictionary<string, int> Visits { get; set; } also is defined, so I still working to find out how to connect this.

    It fails even with one of this model.Visits.Add("John Doe", 1); inside the foreach loop if looping more than 1 times, but it work outside of the loop - even if adding model.Visits.Add("John Doe", 1) more than 1 time.

  • Kevin Jump 2327 posts 14813 karma points MVP 8x c-trib
    Sep 08, 2017 @ 14:47
    Kevin Jump
    1

    Hi

    Dictionary Keys have to be unique so it's possible it fails if the string is the same more than once?

    if that's possible then you either need to check

    if (!Model.Visits.ContainsKey(name)) {
       Model.Visits.Add(name, points);
    }
    

    or use a List and a model so you can have multiple values.

    Model.Visits = new List<VisitInfo>();
    
    Model.Visits.Add(new VisitInfo { Name = name, Point = points });
    
    // info for the list
    public class VisitInfo {
      public string Name {get;set;}
      public string Points {get;set;}
    }
    
  • Tom Engan 430 posts 1173 karma points
    Sep 08, 2017 @ 15:28
    Tom Engan
    0

    Yes that is correct. I just figure out that an error message came when the key was not unique, so I've used the dictonary in the wrong way. (the number of visits can't be unique).

    Well, then there will be a longer break here, but before I go: What's the Model.Visits in your example? Which of my models is this thought taken from (see the example below)? model.Visits = new List<VisitInfo>(); gives me an error (cant convert... etc, and I use small m in model).

    Thanks in advance for any response that may come.

  • Kevin Jump 2327 posts 14813 karma points MVP 8x c-trib
    Sep 08, 2017 @ 16:55
    Kevin Jump
    1

    Hi yeah

    i think the Model.Visits would be from HikingDestinationViewModel

    so if you can you would need to change the definition of the HikingDestinationViewModel Visits property in the class

    From something like

    Dictionary<string, int>Visits  {get;set} 
    

    To

    List<VisitInfo>() Visits {get;set;}
    
  • Tom Engan 430 posts 1173 karma points
    Sep 08, 2017 @ 17:31
    Tom Engan
    0

    Yes, it look like that makes sense. I give feedback when I've finally returned to the office to test the modification of HikingDestinationViewModel. Thanks.

  • Tom Engan 430 posts 1173 karma points
    Sep 11, 2017 @ 11:56
    Tom Engan
    0

    Yes, this works excellent. Now that the VisitInfo class can receive all kinds of numbers, not just unique, printing works as intended. Then only the actual calculations remain. Thank you for your help.

  • Tom Engan 430 posts 1173 karma points
    Sep 07, 2017 @ 14:45
    Tom Engan
    0

    Thanks, this looks promising and I will test it. The next thing I need to figure out now, is how I return the result from the Dictionary defind in model, from the inside of the loop, and out to the view (still error in view).

    // Find all registered hiking destinations from all members, from the dbTable HikingDestinations:
    IEnumerable<HikingDestinationViewModel> allHikingDestinations = HikingDestinations.GetAll();
    
    // where hikingDestination.HikingCode (pr. hiking destination, given from admin)   
    // match members typed code, add some point (pr. hiking destination, given from admin)     
    // and set the members name and points to Dictionary<string, int> Visits (model HikingDestinationViewModel)     
    
    HikingDestinationViewModel model = new HikingDestinationViewModel();
    model.Visits = new Dictionary<string, int>();
    int points = 0;
    foreach (HikingDestinationViewModel hikingDestination in allHikingDestinations)
    {
        points = hikingDestination.HikingCode.ToLower() == hdcode.ToLower() ? points + point : points;
        model.Visits.Add(Members.GetById(hikingDestination.nodeId).Name, points );
    }
    return PartialView("HikingDestinationMenu", model);
    
Please Sign in or register to post replies

Write your reply to:

Draft