switch mod update endpoint to GET with comma-delimited mod keys (#336)
This commit is contained in:
parent
ef60b8d32a
commit
86e5559678
|
@ -29,13 +29,13 @@ namespace StardewModdingAPI.Web.Controllers
|
|||
** Public methods
|
||||
*********/
|
||||
/// <summary>Fetch version metadata for the given mods.</summary>
|
||||
/// <param name="search">The mod update search criteria.</param>
|
||||
[HttpPost]
|
||||
public async Task<ModInfoModel[]> Post([FromBody] ModSearchModel search)
|
||||
/// <param name="modKeys">The namespaced mod keys to search.</param>
|
||||
[HttpGet]
|
||||
public async Task<ModInfoModel[]> Post(IEnumerable<string> modKeys)
|
||||
{
|
||||
IList<ModInfoModel> result = new List<ModInfoModel>();
|
||||
|
||||
foreach (string modKey in search.ModKeys)
|
||||
foreach (string modKey in modKeys)
|
||||
{
|
||||
// parse mod key
|
||||
if (!this.TryParseModKey(modKey, out string vendorKey, out string modID))
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace StardewModdingAPI.Web.Framework
|
||||
{
|
||||
/// <summary>Maps comma-delimited values to an <see cref="System.Collections.Generic.IEnumerable{T}"/> parameter.</summary>
|
||||
/// <remarks>Derived from <a href="https://stackoverflow.com/a/43655986/262123" />.</remarks>
|
||||
public class CommaDelimitedModelBinder : IModelBinder
|
||||
{
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Attempts to bind a model.</summary>
|
||||
/// <param name="bindingContext">The model binding context.</param>
|
||||
public Task BindModelAsync(ModelBindingContext bindingContext)
|
||||
{
|
||||
// validate
|
||||
if (bindingContext == null)
|
||||
throw new ArgumentNullException(nameof(bindingContext));
|
||||
|
||||
// extract values
|
||||
string modelName = bindingContext.ModelName;
|
||||
ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
|
||||
string[] values = valueProviderResult
|
||||
.ToString()
|
||||
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
Type elementType = bindingContext.ModelType.GetTypeInfo().GenericTypeArguments[0];
|
||||
if (values.Length == 0)
|
||||
{
|
||||
bindingContext.Result = ModelBindingResult.Success(Array.CreateInstance(elementType, 0));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
// map values
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(elementType);
|
||||
Array typedArray = Array.CreateInstance(elementType, values.Length);
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < values.Length; ++i)
|
||||
{
|
||||
string value = values[i];
|
||||
object convertedValue = converter.ConvertFromString(value);
|
||||
typedArray.SetValue(convertedValue, i);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
bindingContext.ModelState.TryAddModelError(modelName, exception, bindingContext.ModelMetadata);
|
||||
}
|
||||
|
||||
bindingContext.Result = ModelBindingResult.Success(typedArray);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
|
||||
namespace StardewModdingAPI.Web.Framework
|
||||
{
|
||||
/// <summary>Provides comma-delimited model binds for mapping parameters.</summary>
|
||||
/// <remarks>Derived from <a href="https://stackoverflow.com/a/43655986/262123" />.</remarks>
|
||||
public class CommaDelimitedModelBinderProvider : IModelBinderProvider
|
||||
{
|
||||
/*********
|
||||
** Public methods
|
||||
*********/
|
||||
/// <summary>Creates a model binder based on the given context.</summary>
|
||||
/// <param name="context">The model binding context.</param>
|
||||
public IModelBinder GetBinder(ModelBinderProviderContext context)
|
||||
{
|
||||
// validate
|
||||
if (context == null)
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
|
||||
// get model binder
|
||||
return context.Metadata.IsEnumerableType && !context.Metadata.ElementMetadata.IsComplexType
|
||||
? new CommaDelimitedModelBinder()
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace StardewModdingAPI.Web.Models
|
||||
{
|
||||
/// <summary>The mod update search criteria.</summary>
|
||||
public class ModSearchModel
|
||||
{
|
||||
/// <summary>The namespaced mod keys to search.</summary>
|
||||
public string[] ModKeys { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using StardewModdingAPI.Web.Framework;
|
||||
|
||||
namespace StardewModdingAPI.Web
|
||||
{
|
||||
|
@ -35,7 +38,13 @@ namespace StardewModdingAPI.Web
|
|||
/// <param name="services">The service injection container.</param>
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMvc();
|
||||
services
|
||||
.AddMvc(options =>
|
||||
{
|
||||
// add support for comma-delimited parameters
|
||||
ArrayModelBinderProvider arrayModelBinderProvider = options.ModelBinderProviders.OfType<ArrayModelBinderProvider>().First();
|
||||
options.ModelBinderProviders.Insert(options.ModelBinderProviders.IndexOf(arrayModelBinderProvider), new CommaDelimitedModelBinderProvider());
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>The method called by the runtime to configure the HTTP request pipeline.</summary>
|
||||
|
|
Loading…
Reference in New Issue