diff --git a/src/Servers/HttpSys/src/HttpSysListener.cs b/src/Servers/HttpSys/src/HttpSysListener.cs
index dcb9023007e5d3025fdcb1281d2fa2d195ead483..42b63fea7137d097a5ebbdc3dfa18bc328b3d41d 100644
--- a/src/Servers/HttpSys/src/HttpSysListener.cs
+++ b/src/Servers/HttpSys/src/HttpSysListener.cs
@@ -77,9 +77,9 @@ internal partial class HttpSysListener : IDisposable
         {
             _serverSession = new ServerSession();
 
-            _urlGroup = new UrlGroup(_serverSession, Logger);
+            _requestQueue = new RequestQueue(options.RequestQueueName, options.RequestQueueMode, Logger);
 
-            _requestQueue = new RequestQueue(_urlGroup, options.RequestQueueName, options.RequestQueueMode, Logger);
+            _urlGroup = new UrlGroup(_serverSession, _requestQueue, Logger);
 
             _disconnectListener = new DisconnectListener(_requestQueue, Logger);
         }
@@ -147,12 +147,12 @@ internal partial class HttpSysListener : IDisposable
                     return;
                 }
 
-                // If this instance created the queue then configure it.
-                if (_requestQueue.Created)
+                // Always configure the UrlGroup if the intent was to create, only configure the queue if we actually created it
+                if (Options.RequestQueueMode == RequestQueueMode.Create || Options.RequestQueueMode == RequestQueueMode.CreateOrAttach)
                 {
-                    Options.Apply(UrlGroup, RequestQueue);
+                    Options.Apply(UrlGroup, _requestQueue.Created ? RequestQueue : null);
 
-                    _requestQueue.AttachToUrlGroup();
+                    UrlGroup.AttachToQueue();
 
                     // All resources are set up correctly. Now add all prefixes.
                     try
@@ -162,7 +162,7 @@ internal partial class HttpSysListener : IDisposable
                     catch (HttpSysException)
                     {
                         // If an error occurred while adding prefixes, free all resources allocated by previous steps.
-                        _requestQueue.DetachFromUrlGroup();
+                        UrlGroup.DetachFromQueue();
                         throw;
                     }
                 }
@@ -194,11 +194,11 @@ internal partial class HttpSysListener : IDisposable
 
                 Log.ListenerStopping(Logger);
 
-                // If this instance created the queue then remove the URL prefixes before shutting down.
-                if (_requestQueue.Created)
+                // If this instance registered URL prefixes then remove them before shutting down.
+                if (Options.RequestQueueMode == RequestQueueMode.Create || Options.RequestQueueMode == RequestQueueMode.CreateOrAttach)
                 {
                     Options.UrlPrefixes.UnregisterAllPrefixes();
-                    _requestQueue.DetachFromUrlGroup();
+                    UrlGroup.DetachFromQueue();
                 }
 
                 _state = State.Stopped;
diff --git a/src/Servers/HttpSys/src/HttpSysOptions.cs b/src/Servers/HttpSys/src/HttpSysOptions.cs
index 8db5f9f03982e67eae2872dbe5c51d28720cc7b2..f5eded3da02b417b8b754e0f675c34d0e9b328f8 100644
--- a/src/Servers/HttpSys/src/HttpSysOptions.cs
+++ b/src/Servers/HttpSys/src/HttpSysOptions.cs
@@ -238,7 +238,7 @@ public class HttpSysOptions
     public bool UseLatin1RequestHeaders { get; set; }
 
     // Not called when attaching to an existing queue.
-    internal void Apply(UrlGroup urlGroup, RequestQueue requestQueue)
+    internal void Apply(UrlGroup urlGroup, RequestQueue? requestQueue)
     {
         _urlGroup = urlGroup;
         _requestQueue = requestQueue;
@@ -248,14 +248,17 @@ public class HttpSysOptions
             _urlGroup.SetMaxConnections(_maxConnections.Value);
         }
 
-        if (_requestQueueLength != DefaultRequestQueueLength)
+        if (_requestQueue is not null)
         {
-            _requestQueue.SetLengthLimit(_requestQueueLength);
-        }
+            if (_requestQueueLength != DefaultRequestQueueLength)
+            {
+                _requestQueue.SetLengthLimit(_requestQueueLength);
+            }
 
-        if (_rejectionVebosityLevel != DefaultRejectionVerbosityLevel)
-        {
-            _requestQueue.SetRejectionVerbosity(_rejectionVebosityLevel);
+            if (_rejectionVebosityLevel != DefaultRejectionVerbosityLevel)
+            {
+                _requestQueue.SetRejectionVerbosity(_rejectionVebosityLevel);
+            }
         }
 
         Authentication.SetUrlGroupSecurity(urlGroup);
diff --git a/src/Servers/HttpSys/src/MessagePump.cs b/src/Servers/HttpSys/src/MessagePump.cs
index 8420716c267a997635bad90c6d898025d4dbd6d0..61217208faf0ea749bdc437e805128d9937c5b1c 100644
--- a/src/Servers/HttpSys/src/MessagePump.cs
+++ b/src/Servers/HttpSys/src/MessagePump.cs
@@ -53,7 +53,7 @@ internal partial class MessagePump : IServer
 
         if (HttpApi.SupportsDelegation)
         {
-            var delegationProperty = new ServerDelegationPropertyFeature(Listener.RequestQueue, _logger);
+            var delegationProperty = new ServerDelegationPropertyFeature(Listener.UrlGroup, _logger);
             Features.Set<IServerDelegationFeature>(delegationProperty);
         }
 
diff --git a/src/Servers/HttpSys/src/NativeInterop/RequestQueue.cs b/src/Servers/HttpSys/src/NativeInterop/RequestQueue.cs
index eb235706b44be40e67fe3f6e6c7e02b0d9a4783e..7b99862f05e39768569c32d8620699347f395f32 100644
--- a/src/Servers/HttpSys/src/NativeInterop/RequestQueue.cs
+++ b/src/Servers/HttpSys/src/NativeInterop/RequestQueue.cs
@@ -10,26 +10,22 @@ namespace Microsoft.AspNetCore.Server.HttpSys;
 
 internal sealed partial class RequestQueue
 {
-    private static readonly int BindingInfoSize =
-        Marshal.SizeOf<HttpApiTypes.HTTP_BINDING_INFO>();
-
     private readonly RequestQueueMode _mode;
     private readonly ILogger _logger;
     private bool _disposed;
 
     internal RequestQueue(string requestQueueName, ILogger logger)
-        : this(urlGroup: null, requestQueueName, RequestQueueMode.Attach, logger, receiver: true)
+        : this(requestQueueName, RequestQueueMode.Attach, logger, receiver: true)
     {
     }
 
-    internal RequestQueue(UrlGroup urlGroup, string? requestQueueName, RequestQueueMode mode, ILogger logger)
-        : this(urlGroup, requestQueueName, mode, logger, false)
+    internal RequestQueue(string? requestQueueName, RequestQueueMode mode, ILogger logger)
+        : this(requestQueueName, mode, logger, false)
     { }
 
-    private RequestQueue(UrlGroup? urlGroup, string? requestQueueName, RequestQueueMode mode, ILogger logger, bool receiver)
+    private RequestQueue(string? requestQueueName, RequestQueueMode mode, ILogger logger, bool receiver)
     {
         _mode = mode;
-        UrlGroup = urlGroup;
         _logger = logger;
 
         var flags = HttpApiTypes.HTTP_CREATE_REQUEST_QUEUE_FLAG.None;
@@ -106,55 +102,6 @@ internal sealed partial class RequestQueue
     internal SafeHandle Handle { get; }
     internal ThreadPoolBoundHandle BoundHandle { get; }
 
-    internal UrlGroup? UrlGroup { get; }
-
-    internal unsafe void AttachToUrlGroup()
-    {
-        if (UrlGroup == null)
-        {
-            throw new NotSupportedException("Can't attach when UrlGroup is null");
-        }
-
-        Debug.Assert(Created);
-        CheckDisposed();
-        // Set the association between request queue and url group. After this, requests for registered urls will
-        // get delivered to this request queue.
-
-        var info = new HttpApiTypes.HTTP_BINDING_INFO();
-        info.Flags = HttpApiTypes.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
-        info.RequestQueueHandle = Handle.DangerousGetHandle();
-
-        var infoptr = new IntPtr(&info);
-
-        UrlGroup.SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
-            infoptr, (uint)BindingInfoSize);
-    }
-
-    internal unsafe void DetachFromUrlGroup()
-    {
-        if (UrlGroup == null)
-        {
-            throw new NotSupportedException("Can't detach when UrlGroup is null");
-        }
-
-        Debug.Assert(Created);
-        CheckDisposed();
-        // Break the association between request queue and url group. After this, requests for registered urls
-        // will get 503s.
-        // Note that this method may be called multiple times (Stop() and then Abort()). This
-        // is fine since http.sys allows to set HttpServerBindingProperty multiple times for valid
-        // Url groups.
-
-        var info = new HttpApiTypes.HTTP_BINDING_INFO();
-        info.Flags = HttpApiTypes.HTTP_FLAGS.NONE;
-        info.RequestQueueHandle = IntPtr.Zero;
-
-        var infoptr = new IntPtr(&info);
-
-        UrlGroup.SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
-            infoptr, (uint)BindingInfoSize, throwOnError: false);
-    }
-
     // The listener must be active for this to work.
     internal unsafe void SetLengthLimit(long length)
     {
diff --git a/src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs b/src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs
index 06ebd23a8bbc783e1db6e889bb80c1f5ee81aab3..0a446a4523ec24a7bb884dd1f54dbaebb5ae19f3 100644
--- a/src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs
+++ b/src/Servers/HttpSys/src/NativeInterop/UrlGroup.cs
@@ -10,6 +10,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys;
 
 internal partial class UrlGroup : IDisposable
 {
+    private static readonly int BindingInfoSize =
+        Marshal.SizeOf<HttpApiTypes.HTTP_BINDING_INFO>();
     private static readonly int QosInfoSize =
         Marshal.SizeOf<HttpApiTypes.HTTP_QOS_SETTING_INFO>();
     private static readonly int RequestPropertyInfoSize =
@@ -18,12 +20,14 @@ internal partial class UrlGroup : IDisposable
     private readonly ILogger _logger;
 
     private readonly ServerSession? _serverSession;
+    private readonly RequestQueue _requestQueue;
     private bool _disposed;
     private readonly bool _created;
 
-    internal unsafe UrlGroup(ServerSession serverSession, ILogger logger)
+    internal unsafe UrlGroup(ServerSession serverSession, RequestQueue requestQueue, ILogger logger)
     {
         _serverSession = serverSession;
+        _requestQueue = requestQueue;
         _logger = logger;
 
         ulong urlGroupId = 0;
@@ -91,6 +95,41 @@ internal partial class UrlGroup : IDisposable
         }
     }
 
+    internal unsafe void AttachToQueue()
+    {
+        CheckDisposed();
+        // Set the association between request queue and url group. After this, requests for registered urls will
+        // get delivered to this request queue.
+
+        var info = new HttpApiTypes.HTTP_BINDING_INFO();
+        info.Flags = HttpApiTypes.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
+        info.RequestQueueHandle = _requestQueue.Handle.DangerousGetHandle();
+
+        var infoptr = new IntPtr(&info);
+
+        SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
+            infoptr, (uint)BindingInfoSize);
+    }
+
+    internal unsafe void DetachFromQueue()
+    {
+        CheckDisposed();
+        // Break the association between request queue and url group. After this, requests for registered urls
+        // will get 503s.
+        // Note that this method may be called multiple times (Stop() and then Abort()). This
+        // is fine since http.sys allows to set HttpServerBindingProperty multiple times for valid
+        // Url groups.
+
+        var info = new HttpApiTypes.HTTP_BINDING_INFO();
+        info.Flags = HttpApiTypes.HTTP_FLAGS.NONE;
+        info.RequestQueueHandle = IntPtr.Zero;
+
+        var infoptr = new IntPtr(&info);
+
+        SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
+            infoptr, (uint)BindingInfoSize, throwOnError: false);
+    }
+
     internal void RegisterPrefix(string uriPrefix, int contextId)
     {
         Log.RegisteringPrefix(_logger, uriPrefix);
@@ -101,6 +140,22 @@ internal partial class UrlGroup : IDisposable
         {
             if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_ALREADY_EXISTS)
             {
+                // If we didn't create the queue and the uriPrefix already exists, confirm it exists for the
+                // queue we attached to, if so we are all good, otherwise throw an already registered error.
+                if (!_requestQueue.Created)
+                {
+                    unsafe
+                    {
+                        ulong urlGroupId;
+                        var findUrlStatusCode = HttpApi.HttpFindUrlGroupId(uriPrefix, _requestQueue.Handle, &urlGroupId);
+                        if (findUrlStatusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
+                        {
+                            // Already registered for the desired queue, all good
+                            return;
+                        }
+                    }
+                }
+
                 throw new HttpSysException((int)statusCode, Resources.FormatException_PrefixAlreadyRegistered(uriPrefix));
             }
             if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_ACCESS_DENIED)
@@ -111,18 +166,12 @@ internal partial class UrlGroup : IDisposable
         }
     }
 
-    internal bool UnregisterPrefix(string uriPrefix)
+    internal void UnregisterPrefix(string uriPrefix)
     {
         Log.UnregisteringPrefix(_logger, uriPrefix);
         CheckDisposed();
 
-        var statusCode = HttpApi.HttpRemoveUrlFromUrlGroup(Id, uriPrefix, 0);
-
-        if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_NOT_FOUND)
-        {
-            return false;
-        }
-        return true;
+        HttpApi.HttpRemoveUrlFromUrlGroup(Id, uriPrefix, 0);
     }
 
     public void Dispose()
diff --git a/src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs b/src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs
index ccdb71c1742fcaf16d109987c5d9deeb771cc258..143f0c06fe6929a42a5d0716d5cb4724db078ec4 100644
--- a/src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs
+++ b/src/Servers/HttpSys/src/ServerDelegationPropertyFeature.cs
@@ -10,14 +10,9 @@ internal class ServerDelegationPropertyFeature : IServerDelegationFeature
     private readonly ILogger _logger;
     private readonly UrlGroup _urlGroup;
 
-    public ServerDelegationPropertyFeature(RequestQueue queue, ILogger logger)
+    public ServerDelegationPropertyFeature(UrlGroup urlGroup, ILogger logger)
     {
-        if (queue.UrlGroup == null)
-        {
-            throw new ArgumentException($"{nameof(queue)}.UrlGroup can't be null");
-        }
-
-        _urlGroup = queue.UrlGroup;
+        _urlGroup = urlGroup ?? throw new ArgumentNullException(nameof(urlGroup));
         _logger = logger;
     }
 
diff --git a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
index b3db093023533e11f7a6d3d4f0b525646ad829ac..f1792fb824b0f0a236d0f2b65e7030257f217d8e 100644
--- a/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
+++ b/src/Servers/HttpSys/test/FunctionalTests/DelegateTests.cs
@@ -227,9 +227,7 @@ public class DelegateTests
         // Stop the receiver
         receiver?.Dispose();
 
-        // Start the receiver again but this time we need to attach to the existing queue.
-        // Due to https://github.com/dotnet/aspnetcore/issues/40359, we have to manually
-        // register URL prefixes and attach the server's queue to them.
+        // Start the receiver again but this time we need to use CreateOrAttach to attach to the existing queue and setup the UrlPrefixes
         using var receiverRestarted = (MessagePump)Utilities.CreateHttpServer(out receiverAddress, async httpContext =>
         {
             await httpContext.Response.WriteAsync(_expectedResponseString);
@@ -237,12 +235,10 @@ public class DelegateTests
         options =>
         {
             options.RequestQueueName = queueName;
-            options.RequestQueueMode = RequestQueueMode.Attach;
+            options.RequestQueueMode = RequestQueueMode.CreateOrAttach;
             options.UrlPrefixes.Clear();
             options.UrlPrefixes.Add(receiverAddress);
         });
-        AttachToUrlGroup(receiverRestarted.Listener.RequestQueue);
-        receiverRestarted.Listener.Options.UrlPrefixes.RegisterAllPrefixes(receiverRestarted.Listener.UrlGroup);
 
         responseString = await SendRequestAsync(delegatorAddress);
         Assert.Equal(_expectedResponseString, responseString);
@@ -250,18 +246,6 @@ public class DelegateTests
         destination?.Dispose();
     }
 
-    private unsafe void AttachToUrlGroup(RequestQueue requestQueue)
-    {
-        var info = new HttpApiTypes.HTTP_BINDING_INFO();
-        info.Flags = HttpApiTypes.HTTP_FLAGS.HTTP_PROPERTY_FLAG_PRESENT;
-        info.RequestQueueHandle = requestQueue.Handle.DangerousGetHandle();
-
-        var infoptr = new IntPtr(&info);
-
-        requestQueue.UrlGroup.SetProperty(HttpApiTypes.HTTP_SERVER_PROPERTY.HttpServerBindingProperty,
-            infoptr, (uint)Marshal.SizeOf<HttpApiTypes.HTTP_BINDING_INFO>());
-    }
-
     private async Task<string> SendRequestAsync(string uri)
     {
         using var client = new HttpClient();
diff --git a/src/Servers/HttpSys/test/FunctionalTests/Listener/AuthenticationOnExistingQueueTests.cs b/src/Servers/HttpSys/test/FunctionalTests/Listener/AuthenticationOnExistingQueueTests.cs
index aa161858623826be3fd947cdd72f023b8561fd6c..8e1d611801b83ad77ceb7805cee1934d4bd58a11 100644
--- a/src/Servers/HttpSys/test/FunctionalTests/Listener/AuthenticationOnExistingQueueTests.cs
+++ b/src/Servers/HttpSys/test/FunctionalTests/Listener/AuthenticationOnExistingQueueTests.cs
@@ -10,7 +10,37 @@ using Xunit;
 
 namespace Microsoft.AspNetCore.Server.HttpSys.Listener;
 
-public class AuthenticationOnExistingQueueTests
+public class AuthenticationOnExistingQueueTests_Attach : AuthenticationOnExistingQueueTests
+{
+    protected override string ConfigureServer(HttpSysOptions options, string baseServerAddress)
+    {
+        options.RequestQueueMode = RequestQueueMode.Attach;
+        return baseServerAddress;
+    }
+}
+
+public class AuthenticationOnExistingQueueTests_CreateOrAttach_UseExistingUrlPrefix : AuthenticationOnExistingQueueTests
+{
+    protected override string ConfigureServer(HttpSysOptions options, string baseServerAddress)
+    {
+        options.RequestQueueMode = RequestQueueMode.CreateOrAttach;
+        return baseServerAddress;
+    }
+}
+
+public class AuthenticationOnExistingQueueTests_CreateOrAttach_UseNewUrlPrefix : AuthenticationOnExistingQueueTests
+{
+    protected override string ConfigureServer(HttpSysOptions options, string baseServerAddress)
+    {
+        options.RequestQueueMode = RequestQueueMode.CreateOrAttach;
+        var basePrefix = UrlPrefix.Create(baseServerAddress);
+        var prefix = UrlPrefix.Create(basePrefix.Scheme, basePrefix.Host, basePrefix.Port, "/server");
+        options.UrlPrefixes.Add(prefix);
+        return prefix.ToString();
+    }
+}
+
+public abstract class AuthenticationOnExistingQueueTests
 {
     private static readonly bool AllowAnoymous = true;
     private static readonly bool DenyAnoymous = false;
@@ -24,8 +54,8 @@ public class AuthenticationOnExistingQueueTests
     [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationSchemes.Digest |*/ AuthenticationSchemes.Basic)]
     public async Task AuthTypes_AllowAnonymous_NoChallenge(AuthenticationSchemes authType)
     {
-        using var baseServer = Utilities.CreateHttpAuthServer(authType, AllowAnoymous, out var address);
-        using var server = Utilities.CreateServerOnExistingQueue(authType, AllowAnoymous, baseServer.Options.RequestQueueName);
+        using var baseServer = CreateHttpAuthServer(authType, AllowAnoymous);
+        using var server = CreateServerOnExistingQueue(authType, AllowAnoymous, baseServer, out var address);
 
         Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
 
@@ -47,8 +77,8 @@ public class AuthenticationOnExistingQueueTests
     [InlineData(AuthenticationSchemes.Basic)]
     public async Task AuthType_RequireAuth_ChallengesAdded(AuthenticationSchemes authType)
     {
-        using var baseServer = Utilities.CreateHttpAuthServer(authType, DenyAnoymous, out var address);
-        using var server = Utilities.CreateServerOnExistingQueue(authType, DenyAnoymous, baseServer.Options.RequestQueueName);
+        using var baseServer = CreateHttpAuthServer(authType, DenyAnoymous);
+        using var server = CreateServerOnExistingQueue(authType, DenyAnoymous, baseServer, out var address);
 
         Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
 
@@ -65,8 +95,8 @@ public class AuthenticationOnExistingQueueTests
     [InlineData(AuthenticationSchemes.Basic)]
     public async Task AuthType_AllowAnonymousButSpecify401_ChallengesAdded(AuthenticationSchemes authType)
     {
-        using var baseServer = Utilities.CreateHttpAuthServer(authType, AllowAnoymous, out var address);
-        using var server = Utilities.CreateServerOnExistingQueue(authType, AllowAnoymous, baseServer.Options.RequestQueueName);
+        using var baseServer = CreateHttpAuthServer(authType, AllowAnoymous);
+        using var server = CreateServerOnExistingQueue(authType, AllowAnoymous, baseServer, out var address);
 
         Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
 
@@ -90,8 +120,8 @@ public class AuthenticationOnExistingQueueTests
             | AuthenticationSchemes.NTLM
             /* | AuthenticationSchemes.Digest TODO: Not implemented */
             | AuthenticationSchemes.Basic;
-        using var baseServer = Utilities.CreateHttpAuthServer(authType, AllowAnoymous, out var address);
-        using var server = Utilities.CreateServerOnExistingQueue(authType, AllowAnoymous, baseServer.Options.RequestQueueName);
+        using var baseServer = CreateHttpAuthServer(authType, AllowAnoymous);
+        using var server = CreateServerOnExistingQueue(authType, AllowAnoymous, baseServer, out var address);
 
         Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
 
@@ -115,8 +145,8 @@ public class AuthenticationOnExistingQueueTests
     [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationType.Digest |*/ AuthenticationSchemes.Basic)]
     public async Task AuthTypes_AllowAnonymousButSpecify401_Success(AuthenticationSchemes authType)
     {
-        using var baseServer = Utilities.CreateHttpAuthServer(authType, AllowAnoymous, out var address);
-        using var server = Utilities.CreateServerOnExistingQueue(authType, AllowAnoymous, baseServer.Options.RequestQueueName);
+        using var baseServer = CreateHttpAuthServer(authType, AllowAnoymous);
+        using var server = CreateServerOnExistingQueue(authType, AllowAnoymous, baseServer, out var address);
 
         Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true);
 
@@ -145,8 +175,8 @@ public class AuthenticationOnExistingQueueTests
     [InlineData(AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM | /*AuthenticationType.Digest |*/ AuthenticationSchemes.Basic)]
     public async Task AuthTypes_RequireAuth_Success(AuthenticationSchemes authType)
     {
-        using var baseServer = Utilities.CreateHttpAuthServer(authType, DenyAnoymous, out var address);
-        using var server = Utilities.CreateServerOnExistingQueue(authType, DenyAnoymous, baseServer.Options.RequestQueueName);
+        using var baseServer = CreateHttpAuthServer(authType, DenyAnoymous);
+        using var server = CreateServerOnExistingQueue(authType, DenyAnoymous, baseServer, out var address);
 
         Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true);
 
@@ -160,6 +190,32 @@ public class AuthenticationOnExistingQueueTests
         Assert.Equal(HttpStatusCode.OK, response.StatusCode);
     }
 
+    protected abstract string ConfigureServer(HttpSysOptions options, string baseServerAddress);
+
+    private HttpSysListener CreateHttpAuthServer(AuthenticationSchemes authType, bool allowAnonymous)
+    {
+        var server = Utilities.CreateDynamicHttpServer("/baseServer", out var root, out var baseAddress);
+        server.Options.Authentication.Schemes = authType;
+        server.Options.Authentication.AllowAnonymous = allowAnonymous;
+        return server;
+    }
+
+    private HttpSysListener CreateServerOnExistingQueue(AuthenticationSchemes authScheme, bool allowAnonymos, HttpSysListener baseServer, out string address)
+    {
+        string serverAddress = null;
+        var baseServerAddress = baseServer.Options.UrlPrefixes.First().ToString();
+        var server = Utilities.CreateServer(options =>
+        {
+            options.RequestQueueName = baseServer.Options.RequestQueueName;
+            options.Authentication.Schemes = authScheme;
+            options.Authentication.AllowAnonymous = allowAnonymos;
+            serverAddress = ConfigureServer(options, baseServerAddress);
+        });
+
+        address = serverAddress;
+        return server;
+    }
+
     private async Task<HttpResponseMessage> SendRequestAsync(string uri, bool useDefaultCredentials = false)
     {
         HttpClientHandler handler = new HttpClientHandler();
diff --git a/src/Servers/HttpSys/test/FunctionalTests/Listener/ServerOnExistingQueueTests.cs b/src/Servers/HttpSys/test/FunctionalTests/Listener/ServerOnExistingQueueTests.cs
index 0d62957ee31ef8746e4bfe3d5d125f001d09715a..c4ae575303fed4d185541912b40491dd1f600e2c 100644
--- a/src/Servers/HttpSys/test/FunctionalTests/Listener/ServerOnExistingQueueTests.cs
+++ b/src/Servers/HttpSys/test/FunctionalTests/Listener/ServerOnExistingQueueTests.cs
@@ -6,6 +6,7 @@ using System.IO;
 using System.Net.Http;
 using System.Threading;
 using System.Threading.Tasks;
+using Microsoft.AspNetCore.HttpSys.Internal;
 using Microsoft.AspNetCore.Testing;
 using Xunit;
 
@@ -232,6 +233,88 @@ public class ServerOnExistingQueueTests
         Assert.Equal(string.Empty, response);
     }
 
+    [ConditionalFact]
+    public async Task Server_CreateOrAttach_NoUrlPrefix_NewUrlPrefixWorks()
+    {
+        var queueName = Guid.NewGuid().ToString();
+
+        // Create a queue without a UrlGroup or any UrlPrefixes
+        HttpRequestQueueV2Handle requestQueueHandle = null;
+        var statusCode = HttpApi.HttpCreateRequestQueue(
+                HttpApi.Version,
+                queueName,
+                null,
+                0,
+                out requestQueueHandle);
+
+        Assert.True(statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS);
+
+        using var server = Utilities.CreateServer(options =>
+        {
+            options.RequestQueueName = queueName;
+            options.RequestQueueMode = RequestQueueMode.CreateOrAttach;
+            options.UrlPrefixes.Add("http://localhost:0");
+        });
+
+        var address = server.Options.UrlPrefixes.First().FullPrefix;
+
+        var responseTask = SendRequestAsync(address);
+
+        var context = await server.AcceptAsync(Utilities.DefaultTimeout);
+        context.Dispose();
+
+        var response = await responseTask;
+        Assert.Equal(string.Empty, response);
+    }
+
+    [ConditionalFact]
+    public async Task Server_CreateOrAttach_UrlPrefixExist_ExistingUrlPrefixWorks()
+    {
+        using var baseServer = Utilities.CreateHttpServer(out var address);
+        using var server = Utilities.CreateServer(options =>
+        {
+            options.RequestQueueName = baseServer.Options.RequestQueueName;
+            options.RequestQueueMode = RequestQueueMode.CreateOrAttach;
+            options.UrlPrefixes.Add(address);
+        });
+
+        var responseTask = SendRequestAsync(address);
+
+        var context = await server.AcceptAsync(Utilities.DefaultTimeout);
+        context.Dispose();
+
+        var response = await responseTask;
+        Assert.Equal(string.Empty, response);
+    }
+
+    [ConditionalFact]
+    public async Task Server_CreateOrAttach_UrlPrefixExist_NewAndExistingUrlPrefixsWork()
+    {
+        using var baseServer = Utilities.CreateHttpServerReturnRoot("/baseServer", out string rootAddress);
+        using var server = Utilities.CreateServer(options =>
+        {
+            options.RequestQueueName = baseServer.Options.RequestQueueName;
+            options.RequestQueueMode = RequestQueueMode.CreateOrAttach;
+            options.UrlPrefixes.Add(rootAddress + "/server");
+        });
+
+        var responseTask = SendRequestAsync(rootAddress + "/baseServer");
+
+        var context = await server.AcceptAsync(Utilities.DefaultTimeout);
+        context.Dispose();
+
+        var response = await responseTask;
+        Assert.Equal(string.Empty, response);
+
+        responseTask = SendRequestAsync(rootAddress + "/server");
+
+        context = await server.AcceptAsync(Utilities.DefaultTimeout);
+        context.Dispose();
+
+        response = await responseTask;
+        Assert.Equal(string.Empty, response);
+    }
+
     private async Task<string> SendRequestAsync(string uri)
     {
         using HttpClient client = new HttpClient();
diff --git a/src/Servers/HttpSys/test/FunctionalTests/Listener/Utilities.cs b/src/Servers/HttpSys/test/FunctionalTests/Listener/Utilities.cs
index 696fce6f826e83f1ae78293f619fa9cba24665c3..15664bf82119d4e770d65b025a0165004cf0790d 100644
--- a/src/Servers/HttpSys/test/FunctionalTests/Listener/Utilities.cs
+++ b/src/Servers/HttpSys/test/FunctionalTests/Listener/Utilities.cs
@@ -22,14 +22,6 @@ internal static class Utilities
 
     internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15);
 
-    internal static HttpSysListener CreateHttpAuthServer(AuthenticationSchemes authType, bool allowAnonymous, out string baseAddress)
-    {
-        var listener = CreateHttpServer(out baseAddress);
-        listener.Options.Authentication.Schemes = authType;
-        listener.Options.Authentication.AllowAnonymous = allowAnonymous;
-        return listener;
-    }
-
     internal static HttpSysListener CreateHttpServer(out string baseAddress)
     {
         string root;
@@ -90,23 +82,24 @@ internal static class Utilities
         return listener;
     }
 
-    internal static HttpSysListener CreateServerOnExistingQueue(string requestQueueName)
-    {
-        return CreateServerOnExistingQueue(AuthenticationSchemes.None, true, requestQueueName);
-    }
-
-    internal static HttpSysListener CreateServerOnExistingQueue(AuthenticationSchemes authScheme, bool allowAnonymos, string requestQueueName)
+    internal static HttpSysListener CreateServer(Action<HttpSysOptions> configureOptions)
     {
         var options = new HttpSysOptions();
-        options.RequestQueueMode = RequestQueueMode.Attach;
-        options.RequestQueueName = requestQueueName;
-        options.Authentication.Schemes = authScheme;
-        options.Authentication.AllowAnonymous = allowAnonymos;
+        configureOptions(options);
         var listener = new HttpSysListener(options, new LoggerFactory());
         listener.Start();
         return listener;
     }
 
+    internal static HttpSysListener CreateServerOnExistingQueue(string requestQueueName)
+    {
+        return CreateServer(options =>
+        {
+            options.RequestQueueName = requestQueueName;
+            options.RequestQueueMode = RequestQueueMode.Attach;
+        });
+    }
+
     /// <summary>
     /// AcceptAsync extension with timeout. This extension should be used in all tests to prevent
     /// unexpected hangs when a request does not arrive.
diff --git a/src/Servers/HttpSys/test/FunctionalTests/ServerTests.cs b/src/Servers/HttpSys/test/FunctionalTests/ServerTests.cs
index 39c1553a70569192ade766313cd49c4f35782e12..ff897a01e564d1ca8a3df252f5b712b856eae0b0 100644
--- a/src/Servers/HttpSys/test/FunctionalTests/ServerTests.cs
+++ b/src/Servers/HttpSys/test/FunctionalTests/ServerTests.cs
@@ -36,8 +36,10 @@ public class ServerTests
         }
     }
 
-    [ConditionalFact]
-    public async Task Server_ConnectExistingQueueName_Success()
+    [ConditionalTheory]
+    [InlineData(RequestQueueMode.Attach)]
+    [InlineData(RequestQueueMode.CreateOrAttach)]
+    public async Task Server_ConnectExistingQueueName_Success(RequestQueueMode queueMode)
     {
         string address;
         var queueName = Guid.NewGuid().ToString();
@@ -60,7 +62,7 @@ public class ServerTests
         }, options =>
         {
             options.RequestQueueName = queueName;
-            options.RequestQueueMode = RequestQueueMode.Attach;
+            options.RequestQueueMode = queueMode;
         }))
         {
             var psi = new ProcessStartInfo("netsh", "http show servicestate view=requestq")
@@ -71,6 +73,20 @@ public class ServerTests
             process.Start();
             var netshOutput = await process.StandardOutput.ReadToEndAsync();
             Assert.Contains(queueName, netshOutput);
+
+            var prefix = UrlPrefix.Create(address);
+            switch (queueMode)
+            {
+                case RequestQueueMode.Attach:
+                    Assert.Equal("0", prefix.Port);
+
+                    break;
+                case RequestQueueMode.CreateOrAttach:
+                    Assert.NotEqual("0", prefix.Port);
+                    Assert.Contains(address, netshOutput, StringComparison.OrdinalIgnoreCase);
+
+                    break;
+            }
         }
     }
 
@@ -587,8 +603,10 @@ public class ServerTests
         }
     }
 
-    [ConditionalFact]
-    public async Task Server_AttachToExistingQueue_NoIServerAddresses_NoDefaultAdded()
+    [ConditionalTheory]
+    [InlineData(RequestQueueMode.Attach)]
+    [InlineData(RequestQueueMode.CreateOrAttach)]
+    public async Task Server_AttachToExistingQueue_NoIServerAddresses_NoDefaultAdded(RequestQueueMode queueMode)
     {
         var queueName = Guid.NewGuid().ToString();
         using var server = Utilities.CreateHttpServer(out var address, httpContext => Task.CompletedTask, options =>
@@ -598,7 +616,7 @@ public class ServerTests
         using var attachedServer = Utilities.CreatePump(options =>
         {
             options.RequestQueueName = queueName;
-            options.RequestQueueMode = RequestQueueMode.Attach;
+            options.RequestQueueMode = queueMode;
         });
         await attachedServer.StartAsync(new DummyApplication(context => Task.CompletedTask), default);
         var addressesFeature = attachedServer.Features.Get<IServerAddressesFeature>();