Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ASP.NET Versioned API

Introduction

The project in this repository provides a GlobalVersionedPrefixProvider provider and a bare-bones sample implementation of a versioned API with this provider. It implements a custom written GlobalVersionedPrefixProvider and shows how to use an adapter pattern to easily maintain multiple versions of an API within one single project.

Contents

src

The source folder contains the GlobalVersionedPrefixProvider.cs file, you can copy paste the contents of this class at will and use it wherever you please. If you are so kind attribution to "Robin Maenhaut" is always nice 😄

sample

The sample project provides a bare-bones implementation of the GlobalVersionedPrefixProvider as well as an adapter pattern implementation to handle changing data sources or required changes in the business logic.

Implementation

GlobalVersionedPrefixProvider

Long story short, using this provider gives you an easy way to automatically map a controller to a versioned route.

This class can be passed as an argument of the config.MapHttpAttributeRoutes method that can be found in Register method of the WebApiConfig class.

The GlobalVersionedPrefixProvider takes one argument in its constructor. This is the prefix that will be appended to all controllers. For example config.MapHttpAttributeRoutes(new GlobalVersionedPrefixProvider("api")); will produce URIs like <host>/api/<versionandcontroller>

Controller Naming convention

As structured developers we like to give our classes meaningful names. When considering a REST API that can return a list of users we may consider using a name like UsersController with a GET method that returns all users. When working with a versioned API we can change this name to be UsersV1Controller followed by UsersV2Controller.

This is where the GlobalVersionedPrefixProvider steps in again. The provider maps the controller to a certain URI. There are two ways to influence the URI that'll be generated.

  1. Using the RoutePrefix attribute
  2. Based on the controller name

RoutePrefix Attribute

ASP.NET provides a RoutePrefix attribute that can be used on a class, if present the provider will use the specified prefix. For example UsersV2Controller with a global prefix api and route prefix zombies will produce the URI <host>/api/v2/zombies.

Controller Name

If no RoutePrefix attribute is present the provider will read the route from the controller name. The part in front of the version number is considered the controller URI. For example UsersV2Controller with a global prefix api and no route prefix will produce the URI <host>/api/v2/users.


IMPORTANT: Class names do not like dots, so instead we use 'd'. V1.2 becomes V1d2


All that without a sweat!

Adapters

The project also includes an example of the adapter pattern to handle changes in data retrieval.

An interface is used (IExampleAdapter) to dictate the methods that an adapter should implement. This ensures interoperability, you can easily use any version of the adapter in any controller. This becomes possible because the actual implementation is only ever used once, when creating an object within the constructor of the controller.
There are plenty of ways to handle this (the way the example does it, dependency injection, ..) but it is important that the interface is used to store the implementation object in a variable.

The same logic also applies to the methods defined in the interface, you should avoid using List and instead use IEnumerable. his way the implementation can change to any data container that implements IEnumerable without causing any issues.

Contributing

I'm always interested in your ideas and visions. If you see something that could be done better feel free to start an issue and we'll discuss it together. A group can do so much more than one person alone.

About

Sample providing an easy way to create and maintain a versioned API in ASP.NET.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ASP.NET Versioned API

Introduction

The project in this repository provides a GlobalVersionedPrefixProvider provider and a bare-bones sample implementation of a versioned API with this provider. It implements a custom written GlobalVersionedPrefixProvider and shows how to use an adapter pattern to easily maintain multiple versions of an API within one single project.

Contents

src

The source folder contains the GlobalVersionedPrefixProvider.cs file, you can copy paste the contents of this class at will and use it wherever you please. If you are so kind attribution to "Robin Maenhaut" is always nice 😄

sample

The sample project provides a bare-bones implementation of the GlobalVersionedPrefixProvider as well as an adapter pattern implementation to handle changing data sources or required changes in the business logic.

Implementation

GlobalVersionedPrefixProvider

Long story short, using this provider gives you an easy way to automatically map a controller to a versioned route.

This class can be passed as an argument of the config.MapHttpAttributeRoutes method that can be found in Register method of the WebApiConfig class.

The GlobalVersionedPrefixProvider takes one argument in its constructor. This is the prefix that will be appended to all controllers. For example config.MapHttpAttributeRoutes(new GlobalVersionedPrefixProvider("api")); will produce URIs like <host>/api/<versionandcontroller>

Controller Naming convention

As structured developers we like to give our classes meaningful names. When considering a REST API that can return a list of users we may consider using a name like UsersController with a GET method that returns all users. When working with a versioned API we can change this name to be UsersV1Controller followed by UsersV2Controller.

This is where the GlobalVersionedPrefixProvider steps in again. The provider maps the controller to a certain URI. There are two ways to influence the URI that'll be generated.

  1. Using the RoutePrefix attribute
  2. Based on the controller name

RoutePrefix Attribute

ASP.NET provides a RoutePrefix attribute that can be used on a class, if present the provider will use the specified prefix. For example UsersV2Controller with a global prefix api and route prefix zombies will produce the URI <host>/api/v2/zombies.

Controller Name

If no RoutePrefix attribute is present the provider will read the route from the controller name. The part in front of the version number is considered the controller URI. For example UsersV2Controller with a global prefix api and no route prefix will produce the URI <host>/api/v2/users.


IMPORTANT: Class names do not like dots, so instead we use 'd'. V1.2 becomes V1d2


All that without a sweat!

Adapters

The project also includes an example of the adapter pattern to handle changes in data retrieval.

An interface is used (IExampleAdapter) to dictate the methods that an adapter should implement. This ensures interoperability, you can easily use any version of the adapter in any controller. This becomes possible because the actual implementation is only ever used once, when creating an object within the constructor of the controller.
There are plenty of ways to handle this (the way the example does it, dependency injection, ..) but it is important that the interface is used to store the implementation object in a variable.

The same logic also applies to the methods defined in the interface, you should avoid using List and instead use IEnumerable. his way the implementation can change to any data container that implements IEnumerable without causing any issues.

Contributing

I'm always interested in your ideas and visions. If you see something that could be done better feel free to start an issue and we'll discuss it together. A group can do so much more than one person alone.

About

Sample providing an easy way to create and maintain a versioned API in ASP.NET.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ASP.NET Versioned API

Introduction

The project in this repository provides a GlobalVersionedPrefixProvider provider and a bare-bones sample implementation of a versioned API with this provider. It implements a custom written GlobalVersionedPrefixProvider and shows how to use an adapter pattern to easily maintain multiple versions of an API within one single project.

Contents

src

The source folder contains the GlobalVersionedPrefixProvider.cs file, you can copy paste the contents of this class at will and use it wherever you please. If you are so kind attribution to "Robin Maenhaut" is always nice 😄

sample

The sample project provides a bare-bones implementation of the GlobalVersionedPrefixProvider as well as an adapter pattern implementation to handle changing data sources or required changes in the business logic.

Implementation

GlobalVersionedPrefixProvider

Long story short, using this provider gives you an easy way to automatically map a controller to a versioned route.

This class can be passed as an argument of the config.MapHttpAttributeRoutes method that can be found in Register method of the WebApiConfig class.

The GlobalVersionedPrefixProvider takes one argument in its constructor. This is the prefix that will be appended to all controllers. For example config.MapHttpAttributeRoutes(new GlobalVersionedPrefixProvider("api")); will produce URIs like <host>/api/<versionandcontroller>

Controller Naming convention

As structured developers we like to give our classes meaningful names. When considering a REST API that can return a list of users we may consider using a name like UsersController with a GET method that returns all users. When working with a versioned API we can change this name to be UsersV1Controller followed by UsersV2Controller.

This is where the GlobalVersionedPrefixProvider steps in again. The provider maps the controller to a certain URI. There are two ways to influence the URI that'll be generated.

  1. Using the RoutePrefix attribute
  2. Based on the controller name

RoutePrefix Attribute

ASP.NET provides a RoutePrefix attribute that can be used on a class, if present the provider will use the specified prefix. For example UsersV2Controller with a global prefix api and route prefix zombies will produce the URI <host>/api/v2/zombies.

Controller Name

If no RoutePrefix attribute is present the provider will read the route from the controller name. The part in front of the version number is considered the controller URI. For example UsersV2Controller with a global prefix api and no route prefix will produce the URI <host>/api/v2/users.


IMPORTANT: Class names do not like dots, so instead we use 'd'. V1.2 becomes V1d2


All that without a sweat!

Adapters

The project also includes an example of the adapter pattern to handle changes in data retrieval.

An interface is used (IExampleAdapter) to dictate the methods that an adapter should implement. This ensures interoperability, you can easily use any version of the adapter in any controller. This becomes possible because the actual implementation is only ever used once, when creating an object within the constructor of the controller.
There are plenty of ways to handle this (the way the example does it, dependency injection, ..) but it is important that the interface is used to store the implementation object in a variable.

The same logic also applies to the methods defined in the interface, you should avoid using List and instead use IEnumerable. his way the implementation can change to any data container that implements IEnumerable without causing any issues.

Contributing

I'm always interested in your ideas and visions. If you see something that could be done better feel free to start an issue and we'll discuss it together. A group can do so much more than one person alone.

About

Sample providing an easy way to create and maintain a versioned API in ASP.NET.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ASP.NET Versioned API

Introduction

The project in this repository provides a GlobalVersionedPrefixProvider provider and a bare-bones sample implementation of a versioned API with this provider. It implements a custom written GlobalVersionedPrefixProvider and shows how to use an adapter pattern to easily maintain multiple versions of an API within one single project.

Contents

src

The source folder contains the GlobalVersionedPrefixProvider.cs file, you can copy paste the contents of this class at will and use it wherever you please. If you are so kind attribution to "Robin Maenhaut" is always nice 😄

sample

The sample project provides a bare-bones implementation of the GlobalVersionedPrefixProvider as well as an adapter pattern implementation to handle changing data sources or required changes in the business logic.

Implementation

GlobalVersionedPrefixProvider

Long story short, using this provider gives you an easy way to automatically map a controller to a versioned route.

This class can be passed as an argument of the config.MapHttpAttributeRoutes method that can be found in Register method of the WebApiConfig class.

The GlobalVersionedPrefixProvider takes one argument in its constructor. This is the prefix that will be appended to all controllers. For example config.MapHttpAttributeRoutes(new GlobalVersionedPrefixProvider("api")); will produce URIs like <host>/api/<versionandcontroller>

Controller Naming convention

As structured developers we like to give our classes meaningful names. When considering a REST API that can return a list of users we may consider using a name like UsersController with a GET method that returns all users. When working with a versioned API we can change this name to be UsersV1Controller followed by UsersV2Controller.

This is where the GlobalVersionedPrefixProvider steps in again. The provider maps the controller to a certain URI. There are two ways to influence the URI that'll be generated.

  1. Using the RoutePrefix attribute
  2. Based on the controller name

RoutePrefix Attribute

ASP.NET provides a RoutePrefix attribute that can be used on a class, if present the provider will use the specified prefix. For example UsersV2Controller with a global prefix api and route prefix zombies will produce the URI <host>/api/v2/zombies.

Controller Name

If no RoutePrefix attribute is present the provider will read the route from the controller name. The part in front of the version number is considered the controller URI. For example UsersV2Controller with a global prefix api and no route prefix will produce the URI <host>/api/v2/users.


IMPORTANT: Class names do not like dots, so instead we use 'd'. V1.2 becomes V1d2


All that without a sweat!

Adapters

The project also includes an example of the adapter pattern to handle changes in data retrieval.

An interface is used (IExampleAdapter) to dictate the methods that an adapter should implement. This ensures interoperability, you can easily use any version of the adapter in any controller. This becomes possible because the actual implementation is only ever used once, when creating an object within the constructor of the controller.
There are plenty of ways to handle this (the way the example does it, dependency injection, ..) but it is important that the interface is used to store the implementation object in a variable.

The same logic also applies to the methods defined in the interface, you should avoid using List and instead use IEnumerable. his way the implementation can change to any data container that implements IEnumerable without causing any issues.

Contributing

I'm always interested in your ideas and visions. If you see something that could be done better feel free to start an issue and we'll discuss it together. A group can do so much more than one person alone.

About

Sample providing an easy way to create and maintain a versioned API in ASP.NET.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ASP.NET Versioned API

Introduction

The project in this repository provides a GlobalVersionedPrefixProvider provider and a bare-bones sample implementation of a versioned API with this provider. It implements a custom written GlobalVersionedPrefixProvider and shows how to use an adapter pattern to easily maintain multiple versions of an API within one single project.

Contents

src

The source folder contains the GlobalVersionedPrefixProvider.cs file, you can copy paste the contents of this class at will and use it wherever you please. If you are so kind attribution to "Robin Maenhaut" is always nice 😄

sample

The sample project provides a bare-bones implementation of the GlobalVersionedPrefixProvider as well as an adapter pattern implementation to handle changing data sources or required changes in the business logic.

Implementation

GlobalVersionedPrefixProvider

Long story short, using this provider gives you an easy way to automatically map a controller to a versioned route.

This class can be passed as an argument of the config.MapHttpAttributeRoutes method that can be found in Register method of the WebApiConfig class.

The GlobalVersionedPrefixProvider takes one argument in its constructor. This is the prefix that will be appended to all controllers. For example config.MapHttpAttributeRoutes(new GlobalVersionedPrefixProvider("api")); will produce URIs like <host>/api/<versionandcontroller>

Controller Naming convention

As structured developers we like to give our classes meaningful names. When considering a REST API that can return a list of users we may consider using a name like UsersController with a GET method that returns all users. When working with a versioned API we can change this name to be UsersV1Controller followed by UsersV2Controller.

This is where the GlobalVersionedPrefixProvider steps in again. The provider maps the controller to a certain URI. There are two ways to influence the URI that'll be generated.

  1. Using the RoutePrefix attribute
  2. Based on the controller name

RoutePrefix Attribute

ASP.NET provides a RoutePrefix attribute that can be used on a class, if present the provider will use the specified prefix. For example UsersV2Controller with a global prefix api and route prefix zombies will produce the URI <host>/api/v2/zombies.

Controller Name

If no RoutePrefix attribute is present the provider will read the route from the controller name. The part in front of the version number is considered the controller URI. For example UsersV2Controller with a global prefix api and no route prefix will produce the URI <host>/api/v2/users.


IMPORTANT: Class names do not like dots, so instead we use 'd'. V1.2 becomes V1d2


All that without a sweat!

Adapters

The project also includes an example of the adapter pattern to handle changes in data retrieval.

An interface is used (IExampleAdapter) to dictate the methods that an adapter should implement. This ensures interoperability, you can easily use any version of the adapter in any controller. This becomes possible because the actual implementation is only ever used once, when creating an object within the constructor of the controller.
There are plenty of ways to handle this (the way the example does it, dependency injection, ..) but it is important that the interface is used to store the implementation object in a variable.

The same logic also applies to the methods defined in the interface, you should avoid using List and instead use IEnumerable. his way the implementation can change to any data container that implements IEnumerable without causing any issues.

Contributing

I'm always interested in your ideas and visions. If you see something that could be done better feel free to start an issue and we'll discuss it together. A group can do so much more than one person alone.

About

Sample providing an easy way to create and maintain a versioned API in ASP.NET.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ASP.NET Versioned API

Introduction

The project in this repository provides a GlobalVersionedPrefixProvider provider and a bare-bones sample implementation of a versioned API with this provider. It implements a custom written GlobalVersionedPrefixProvider and shows how to use an adapter pattern to easily maintain multiple versions of an API within one single project.

Contents

src

The source folder contains the GlobalVersionedPrefixProvider.cs file, you can copy paste the contents of this class at will and use it wherever you please. If you are so kind attribution to "Robin Maenhaut" is always nice 😄

sample

The sample project provides a bare-bones implementation of the GlobalVersionedPrefixProvider as well as an adapter pattern implementation to handle changing data sources or required changes in the business logic.

Implementation

GlobalVersionedPrefixProvider

Long story short, using this provider gives you an easy way to automatically map a controller to a versioned route.

This class can be passed as an argument of the config.MapHttpAttributeRoutes method that can be found in Register method of the WebApiConfig class.

The GlobalVersionedPrefixProvider takes one argument in its constructor. This is the prefix that will be appended to all controllers. For example config.MapHttpAttributeRoutes(new GlobalVersionedPrefixProvider("api")); will produce URIs like <host>/api/<versionandcontroller>

Controller Naming convention

As structured developers we like to give our classes meaningful names. When considering a REST API that can return a list of users we may consider using a name like UsersController with a GET method that returns all users. When working with a versioned API we can change this name to be UsersV1Controller followed by UsersV2Controller.

This is where the GlobalVersionedPrefixProvider steps in again. The provider maps the controller to a certain URI. There are two ways to influence the URI that'll be generated.

  1. Using the RoutePrefix attribute
  2. Based on the controller name

RoutePrefix Attribute

ASP.NET provides a RoutePrefix attribute that can be used on a class, if present the provider will use the specified prefix. For example UsersV2Controller with a global prefix api and route prefix zombies will produce the URI <host>/api/v2/zombies.

Controller Name

If no RoutePrefix attribute is present the provider will read the route from the controller name. The part in front of the version number is considered the controller URI. For example UsersV2Controller with a global prefix api and no route prefix will produce the URI <host>/api/v2/users.


IMPORTANT: Class names do not like dots, so instead we use 'd'. V1.2 becomes V1d2


All that without a sweat!

Adapters

The project also includes an example of the adapter pattern to handle changes in data retrieval.

An interface is used (IExampleAdapter) to dictate the methods that an adapter should implement. This ensures interoperability, you can easily use any version of the adapter in any controller. This becomes possible because the actual implementation is only ever used once, when creating an object within the constructor of the controller.
There are plenty of ways to handle this (the way the example does it, dependency injection, ..) but it is important that the interface is used to store the implementation object in a variable.

The same logic also applies to the methods defined in the interface, you should avoid using List and instead use IEnumerable. his way the implementation can change to any data container that implements IEnumerable without causing any issues.

Contributing

I'm always interested in your ideas and visions. If you see something that could be done better feel free to start an issue and we'll discuss it together. A group can do so much more than one person alone.

About

Sample providing an easy way to create and maintain a versioned API in ASP.NET.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ASP.NET Versioned API

Introduction

The project in this repository provides a GlobalVersionedPrefixProvider provider and a bare-bones sample implementation of a versioned API with this provider. It implements a custom written GlobalVersionedPrefixProvider and shows how to use an adapter pattern to easily maintain multiple versions of an API within one single project.

Contents

src

The source folder contains the GlobalVersionedPrefixProvider.cs file, you can copy paste the contents of this class at will and use it wherever you please. If you are so kind attribution to "Robin Maenhaut" is always nice 😄

sample

The sample project provides a bare-bones implementation of the GlobalVersionedPrefixProvider as well as an adapter pattern implementation to handle changing data sources or required changes in the business logic.

Implementation

GlobalVersionedPrefixProvider

Long story short, using this provider gives you an easy way to automatically map a controller to a versioned route.

This class can be passed as an argument of the config.MapHttpAttributeRoutes method that can be found in Register method of the WebApiConfig class.

The GlobalVersionedPrefixProvider takes one argument in its constructor. This is the prefix that will be appended to all controllers. For example config.MapHttpAttributeRoutes(new GlobalVersionedPrefixProvider("api")); will produce URIs like <host>/api/<versionandcontroller>

Controller Naming convention

As structured developers we like to give our classes meaningful names. When considering a REST API that can return a list of users we may consider using a name like UsersController with a GET method that returns all users. When working with a versioned API we can change this name to be UsersV1Controller followed by UsersV2Controller.

This is where the GlobalVersionedPrefixProvider steps in again. The provider maps the controller to a certain URI. There are two ways to influence the URI that'll be generated.

  1. Using the RoutePrefix attribute
  2. Based on the controller name

RoutePrefix Attribute

ASP.NET provides a RoutePrefix attribute that can be used on a class, if present the provider will use the specified prefix. For example UsersV2Controller with a global prefix api and route prefix zombies will produce the URI <host>/api/v2/zombies.

Controller Name

If no RoutePrefix attribute is present the provider will read the route from the controller name. The part in front of the version number is considered the controller URI. For example UsersV2Controller with a global prefix api and no route prefix will produce the URI <host>/api/v2/users.


IMPORTANT: Class names do not like dots, so instead we use 'd'. V1.2 becomes V1d2


All that without a sweat!

Adapters

The project also includes an example of the adapter pattern to handle changes in data retrieval.

An interface is used (IExampleAdapter) to dictate the methods that an adapter should implement. This ensures interoperability, you can easily use any version of the adapter in any controller. This becomes possible because the actual implementation is only ever used once, when creating an object within the constructor of the controller.
There are plenty of ways to handle this (the way the example does it, dependency injection, ..) but it is important that the interface is used to store the implementation object in a variable.

The same logic also applies to the methods defined in the interface, you should avoid using List and instead use IEnumerable. his way the implementation can change to any data container that implements IEnumerable without causing any issues.

Contributing

I'm always interested in your ideas and visions. If you see something that could be done better feel free to start an issue and we'll discuss it together. A group can do so much more than one person alone.

About

Sample providing an easy way to create and maintain a versioned API in ASP.NET.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

14 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

ASP.NET Versioned API

Introduction

The project in this repository provides a GlobalVersionedPrefixProvider provider and a bare-bones sample implementation of a versioned API with this provider. It implements a custom written GlobalVersionedPrefixProvider and shows how to use an adapter pattern to easily maintain multiple versions of an API within one single project.

Contents

src

The source folder contains the GlobalVersionedPrefixProvider.cs file, you can copy paste the contents of this class at will and use it wherever you please. If you are so kind attribution to "Robin Maenhaut" is always nice 😄

sample

The sample project provides a bare-bones implementation of the GlobalVersionedPrefixProvider as well as an adapter pattern implementation to handle changing data sources or required changes in the business logic.

Implementation

GlobalVersionedPrefixProvider

Long story short, using this provider gives you an easy way to automatically map a controller to a versioned route.

This class can be passed as an argument of the config.MapHttpAttributeRoutes method that can be found in Register method of the WebApiConfig class.

The GlobalVersionedPrefixProvider takes one argument in its constructor. This is the prefix that will be appended to all controllers. For example config.MapHttpAttributeRoutes(new GlobalVersionedPrefixProvider("api")); will produce URIs like <host>/api/<versionandcontroller>

Controller Naming convention

As structured developers we like to give our classes meaningful names. When considering a REST API that can return a list of users we may consider using a name like UsersController with a GET method that returns all users. When working with a versioned API we can change this name to be UsersV1Controller followed by UsersV2Controller.

This is where the GlobalVersionedPrefixProvider steps in again. The provider maps the controller to a certain URI. There are two ways to influence the URI that'll be generated.

  1. Using the RoutePrefix attribute
  2. Based on the controller name

RoutePrefix Attribute

ASP.NET provides a RoutePrefix attribute that can be used on a class, if present the provider will use the specified prefix. For example UsersV2Controller with a global prefix api and route prefix zombies will produce the URI <host>/api/v2/zombies.

Controller Name

If no RoutePrefix attribute is present the provider will read the route from the controller name. The part in front of the version number is considered the controller URI. For example UsersV2Controller with a global prefix api and no route prefix will produce the URI <host>/api/v2/users.


IMPORTANT: Class names do not like dots, so instead we use 'd'. V1.2 becomes V1d2


All that without a sweat!

Adapters

The project also includes an example of the adapter pattern to handle changes in data retrieval.

An interface is used (IExampleAdapter) to dictate the methods that an adapter should implement. This ensures interoperability, you can easily use any version of the adapter in any controller. This becomes possible because the actual implementation is only ever used once, when creating an object within the constructor of the controller.
There are plenty of ways to handle this (the way the example does it, dependency injection, ..) but it is important that the interface is used to store the implementation object in a variable.

The same logic also applies to the methods defined in the interface, you should avoid using List and instead use IEnumerable. his way the implementation can change to any data container that implements IEnumerable without causing any issues.

Contributing

I'm always interested in your ideas and visions. If you see something that could be done better feel free to start an issue and we'll discuss it together. A group can do so much more than one person alone.

About

Sample providing an easy way to create and maintain a versioned API in ASP.NET.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages