Developer forum

Forum » Development » New URL Provider

New URL Provider

Mafalda Correa
Mafalda Correa
Reply

Hello,

I'm trying to build a custom URL Provider to turn a State query parameter into a country/state url (eg: http://rapido.localtest.me/Default.aspx?ID=123&State=CA turns into http://rapido.localtest.me/test/us/ca)

I started by doing a UrlProvider:

namespace Dna.Winnebago.UrlProviders
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    [Browsable(false)]
    [AddInName("Dealers by state id")]
    [AddInDescription("Generates urls for dealer Directory in the form /countrycode/statecode")]
    [AddInActive(true)]
    [AddInGroup("Dealer Directory")]
    [AddInTarget("QueryPublisher")]
    public class DealerDirectory : UrlProvider
    {
        public override List<Mapping> GetMappings()
        {
            var result = new List<Mapping>();
            
            foreach (var country in Services.Countries.GetCountries())
            {
                foreach (var state in country.Regions)
                {
                    result.Add(new Mapping("State", state.RegionCode, $"{country.Code2}/{state.RegionCode}"));
                }
            }
            
            return result;
        }
    }
}

However I had an issue because I only wanted to apply it to a single page. So, instead, I tried to create UrlDataProvider (aka the new URL provider)

using System;
using System.Collections;
using System.Collections.Generic;
using Dynamicweb.Core;
using Dynamicweb.Ecommerce;
using Dynamicweb.Extensibility.AddIns;
using Dynamicweb.Extensibility.Editors;
using Dynamicweb.Frontend.UrlHandling;

namespace Dna.Winnebago.UrlProviders
{
    [AddInName("Dealer Directory")]
    [AddInOrder(1000)]
    public class DealerDirectoryNew : UrlDataProvider, IDropDownOptions
    {
        public override IEnumerable<UrlDataNode> GetUrlDataNodes(UrlDataNode parent, UrlDataContext dataContext)
        {
            var nodes = new List<UrlDataNode>();
            
            foreach (var country in Services.Countries.GetCountries())
            {
                foreach (var state in country.Regions)
                {
                    nodes.Add(new UrlDataNode()
                    {
                        Id = $"DealerDirectory_{state.RegionCode}",
                        ParentId = parent.Id,
                        PathName = $"{country.Code2}/{state.RegionCode}",
                        IgnoreInChildPath = false,
                        IgnoreParentPath = false,
                        // PathExact = $"{country.Code2}/{state.RegionCode}",
                        QueryStringParameter = "State",
                        QueryStringValue = state.RegionCode,
                        QueryStringExact = string.Empty,
                        IgnoreParentQuerystring = false 
                    });
                }
            }
            
            return nodes;
        }

        public Hashtable GetOptions(string dropdownName)
        {
            var options = new Hashtable();
            return options;
        }
    }
}

This is working almost as expected except that the path name is converting the slash (/) to a dash (-). So I get http://rapido.localtest.me/test/us-ca instead of http://rapido.localtest.me/test/us/ca which is what I need to achieve. I tried using the path exact, which does keep the slash, however it loses the rest of the path, so I can't use that either.

Is there a way I can force the PathName to keep the slash and not change it to a dash? Or is there any way I can achieve what I'm trying to do which is convert http://rapido.localtest.me/Default.aspx?ID=123&State=CA to http://rapido.localtest.me/test/us/ca only in a specific page?

Thanks


Replies

 
Nicolai Pedersen
Reply

Hi Mafalda

URLProviders only works for one part of the url - parts are seperated by /. So in your case 'us' is one part and 'ca' is another part and you cannot handle those as one with URL providers.

So if you change it to Default.aspx?ID=123&country=US&State=CA and create 2 urlproviders, you can achieve it.

Alternatively you can use the newer UrlDataProvider instead you can control the entire URL and querystring relationship.

BR Nicolai

 
Mafalda Correa
Mafalda Correa
Reply

Hi Nicolai,

I believe the new UrlDataProvider is what I'm using in the second example. And that's what's turning my country/state into coutry-state.

With the UrlProvider it actually worked fine and only passing the State=CA it built the correct URL as country/state, the only problem was that I couldn't limit it to that one page.

 
Nicolai Pedersen
Reply

I read only half your post!! cool

Use PathExact instead of PathName when creating that

 
Mafalda Correa
Mafalda Correa
Reply

I also tried that, but if I use PathExact I lose the rest of the information, my full path is actually this:

https://qa.winnebago.com/shopping-tools/dealer-directory?state=CA&selectedState=California&vehicleType=Motorhomes&Group=81&Motorhomes=True&Towables=False

Which I need to convert to be:

https://qa.winnebago.com/shopping-tools/dealer-directory/us/ca?selectedState=California&vehicleType=Motorhomes&Group=81&Motorhomes=True&Towables=False

It doesn't seem like I can use the PathExact without losing the rest of the information in the query string.

 
Nicolai Pedersen
Reply

Well - those are the options available.

If you use pathexact you have to put the entire path in: /shopping-tools/dealer-directory/us/ca  along with setting QueryStringExact to ID=123&state=ca

The simplest for you is to make it country=us&state=ca and then either add 2 urlproviders or use the UrlDataProvider to add nodes in that order.

BR Nicolai

 
Mafalda Correa
Mafalda Correa
Reply

I tried adding a parameter for country and handling country and state parameter in separate nodes. But it's only resolving the first one.

So when I pass:

http://rapido.localtest.me/Default.aspx?ID=216&Country=US&State=CA

It resolves to:

http://rapido.localtest.me/frontpage/test/us?State=CA

What am I doing wrong?

Here's the code:

using System;
using System.Collections;
using System.Collections.Generic;
using Dynamicweb.Core;
using Dynamicweb.Ecommerce;
using Dynamicweb.Extensibility.AddIns;
using Dynamicweb.Extensibility.Editors;
using Dynamicweb.Frontend.UrlHandling;

namespace Dna.Winnebago.UrlProviders
{
    [AddInName("Dealer Directory")]
    [AddInOrder(1000)]
    public class DealerDirectoryNew : UrlDataProvider, IDropDownOptions
    {
        public override IEnumerable<UrlDataNode> GetUrlDataNodes(UrlDataNode parent, UrlDataContext dataContext)
        {
            var nodes = new List<UrlDataNode>();

            foreach (var country in Services.Countries.GetCountries())
            {
                nodes.Add(new UrlDataNode()
                {
                    Id = $"DealerDirectory_{country.Code2}",
                    ParentId = parent.Id,
                    PathName = $"{country.Code2}",
                    IgnoreInChildPath = false,
                    IgnoreParentPath = false,
                    QueryStringParameter = "Country",
                    QueryStringValue = country.Code2,
                    QueryStringExact = string.Empty,
                    IgnoreParentQuerystring = false
                });

                foreach (var state in country.Regions)
                {
                    nodes.Add(new UrlDataNode()
                    {
                        Id = $"DealerDirectory_{state.RegionCode}",
                        ParentId = parent.Id,
                        PathName = $"{state.RegionCode}",
                        IgnoreInChildPath = false,
                        IgnoreParentPath = false,
                        QueryStringParameter = "State",
                        QueryStringValue = state.RegionCode,
                        QueryStringExact = string.Empty,
                        IgnoreParentQuerystring = false
                    });
                }
            }

            return nodes;
        }

        public Hashtable GetOptions(string dropdownName)
        {
            var options = new Hashtable();
            return options;
        }
    }
}
 
Nicolai Pedersen
Reply

You have to set the parentid of your state nodes to the id of the country node ($"DealerDirectory_{country.Code2}").

 
Mafalda Correa
Mafalda Correa
Reply

Alright, that worked, thanks!

 
Magnus Holmberg
Reply

How do I get the UrlDataProvider to activate? 

The UrlProvider you can activate in Customized URLs but the new UrlDataProvider i can't find.

 
Nicolai Pedersen
Reply

Hi Magnus

They work a bit differently. You set them up on the pages where you want the ecommerce URLs to be. See this section:

https://doc.dynamicweb.com/documentation-9/platform/platform-tools/customized-urls#8707

BR Nicolai

 
Magnus Holmberg
Reply

Hi Nicolai,

Thanks!

So its only for ecommerce for now. We need it for rewrite the url for details page on Extranet users, we list our Customer Centers like this https://rental.skanska.se/kontakta-oss.

But when going to the details page the URL has ObejctId instead of Friendly URL https://rental.skanska.se/kontakta-oss?ObjectID=6&Action=Detail. I managed to rewrite it with the UrlProvider so it looks like this https://rental.skanska.se/kontakta-oss/borlange?Action=Detail, https://rental.skanska.se/kontakta-oss/malmo?Action=Detail.... But is it possible to get rid of the Action=Detail?

 

 
Nicolai Pedersen
Reply
This post has been marked as an answer

Hi Magnus

Not out of the box. But you can write either UrlProvider that targets the action=detail or you can develop a UrlDataProvider (the new kind) that targets the entire querystring "ObjectID=6&Action=Detail".

BR Nicolai

Votes for this answer: 1
 
Magnus Holmberg
Reply

Hi Nicolai,
 

It worked perfectly.

Thanks for the help!

Best regards, Magnus

 

 
Nicolai Pedersen
Reply

Cool!

If you do not mind, please post your code bit here for others to get inspiration for!

Thanks, Nicolai

 
Magnus Holmberg
Reply

Here is the code, enjoy smiley:

using System.Collections.Generic;
using Dynamicweb.Content.Items;
using Dynamicweb.Extensibility.AddIns;
using Dynamicweb.Frontend.UrlHandling;
using Dynamicweb.Security.UserManagement;

namespace Mindflower.SomeNameSpace
{
    [AddInName("Kundcenter URL Rewrite")]
    public class CustomerCenterFriendlyUrl : UrlDataProvider
    {
        public override IEnumerable<UrlDataNode> GetUrlDataNodes(UrlDataNode parent, UrlDataContext dataContext)
        {
            var nodes = new List<UrlDataNode>();
            var users = User.GetUsersByGroupID(4);
            var parentPathName = EncodePathName(parent.PathName);
            foreach(var user in users)
            {
                if (!user.Active)
                    continue;

                var item = Item.GetItemById(user.ItemType, user.ItemId);
                item.TryGetValue("Pathname", out object pathNameObject); 
                var pathName = string.IsNullOrEmpty((string)pathNameObject) ? user.Name : (string)pathNameObject;

                nodes.Add(new UrlDataNode()
                {
                    Id = $"CustomerCenter_{user.ID}",
                    ParentId = parent.Id,
                    PathExact = $"/{parentPathName}/{pathName}",
                    IgnoreInChildPath = false,
                    IgnoreParentPath = false,
                    QueryStringExact = $"id={parent.QueryStringValue}&ObjectID={user.ID}&Action=Detail",
                    IgnoreParentQuerystring = false
                });
            }

            return nodes;
        }       
    }
 }

 

You must be logged in to post in the forum