C
C#6mo ago
Raki

How does option work in .net core

I have the below class here the contentfulclient base has a class called ContentfulClientBase which has a property called as contentfuloption with some property. I want to assign the value to one of the property. I have my own contentfuloption class which has some of the properties of ContentfulClientBase class contentfuloption. I want to pass my model value to contentfulclientbase class. But I don't know how to achieve it. When I use _options = options.Value; I get an error states type to type conversion is not possible. Basically I want my baseclass property should get my value which I provide. public class ContentfulManagementService : ContentfulClientBase, IContentfulManagementService { private readonly ILogger<ContentfulManagementService> _logger; private readonly Models.ContentfulOptions _contentfulOptions; public ContentfulManagementService( HttpClient httpClient, ILogger<ContentfulManagementService> logger, IOptions<Models.ContentfulOptions> options) { _httpClient = httpClient; _logger = logger; _contentfulOptions = options.Value; } }
54 Replies
Gramore
Gramore6mo ago
Can you post the specific error? That looks reasonable to me. Just as a nit (more of a style thing) if you just want the options to go to your base class, maybe the base class should have a ctor that takes the options and then you can pass to base in your inheriting class. i.e.
public abstract class ContentfulClientBase
{
// nit: if these are just for the client maybe ContentfulClientOptions
private readonly ContentfulOptions _options;

public ContentfulClientBase(ContentfulOptions options)
{
_options = options
}
}

public class ContentfulManagementService : ContentfulClientBase
{
public ContentfulManagementService(ContentfulOptions options)
:base(options)
{
//other ctor stuff
}
}
public abstract class ContentfulClientBase
{
// nit: if these are just for the client maybe ContentfulClientOptions
private readonly ContentfulOptions _options;

public ContentfulClientBase(ContentfulOptions options)
{
_options = options
}
}

public class ContentfulManagementService : ContentfulClientBase
{
public ContentfulManagementService(ContentfulOptions options)
:base(options)
{
//other ctor stuff
}
}
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
MODiX
MODiX6mo ago
appsettings.json:
{
"My": {
"Foo": {
"Kix": 5
}
}
}
{
"My": {
"Foo": {
"Kix": 5
}
}
}
src/Foo/FooOptions.cs:
public class FooOptions
{
public const string SectionName = "My:Foo";

public string Bar {get;set;} = "default value for bar";
public int Kix {get;set;} = -1;
public DateTime? Pouet {get;set;} = default;
}
public class FooOptions
{
public const string SectionName = "My:Foo";

public string Bar {get;set;} = "default value for bar";
public int Kix {get;set;} = -1;
public DateTime? Pouet {get;set;} = default;
}
src/Foo/FooServiceCollectionExtensions.cs:
namespace Microsoft.Extensions.DependencyInjection; // <==== recommanded for service.Add so that you don't clutter Startup file

public class FooServiceCollectionExtensions
{
public static IServiceCollection AddFoo(this IServiceCollection services) =>
services
.AddOptions<FooOptions>()
.BindConfiguration(FooOptions.SectionName)
.Validate(options => options.Kix >= 0, $"The configuration key '{FooOptions.SectionName}:{nameof(Kix)}' cannot be negative")
;

public static IServiceCollection AddFoo(this IServiceCollection services, Action<FooOptions> configure) =>
services
.AddFoo()
.Configure(configure);
namespace Microsoft.Extensions.DependencyInjection; // <==== recommanded for service.Add so that you don't clutter Startup file

public class FooServiceCollectionExtensions
{
public static IServiceCollection AddFoo(this IServiceCollection services) =>
services
.AddOptions<FooOptions>()
.BindConfiguration(FooOptions.SectionName)
.Validate(options => options.Kix >= 0, $"The configuration key '{FooOptions.SectionName}:{nameof(Kix)}' cannot be negative")
;

public static IServiceCollection AddFoo(this IServiceCollection services, Action<FooOptions> configure) =>
services
.AddFoo()
.Configure(configure);
Program.cs / Startup.cs:
services.AddFoo();
// or
services.AddFoo(fooOptions => fooOptions.Kix = 12);
services.AddFoo();
// or
services.AddFoo(fooOptions => fooOptions.Kix = 12);
Bar.cs:
public class Bar
{
private readonly FooOptions _fooOptions;

// .Value in ctor is fine only if it's always ever a non-changing value (no reload and/or no scoped resolution)
public Bar(IOptions<FooOptions> fooOptions)
=> _fooOptions = fooOptions.Value;
}
public class Bar
{
private readonly FooOptions _fooOptions;

// .Value in ctor is fine only if it's always ever a non-changing value (no reload and/or no scoped resolution)
public Bar(IOptions<FooOptions> fooOptions)
=> _fooOptions = fooOptions.Value;
}
Gramore
Gramore6mo ago
Oh ya doi
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
Tbh i hate using IOptions unless i need the hot reload Just bind and raw dog it
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
nuget / unit tests? How does IOptions help there compared to just the pattern?
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
Lol i mean, injecting MyOptions vs IOptions<MyOptions>
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
I mena you have to bind either way so really it's just more code to .value
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
catshrug
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
preference anywho
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
.Value just makes me sad when it adds no value 😛
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
But also re: the OP question didn't his original look right? (tho that command is 👌)
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
ah i get u
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
depends if it's for the client only or not oh as in ctor ye ye tru
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
private if it's client specific (as OP said)
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
anyway methinks that this whole thing smells like it wants to be using the IHttpClientFactory stuff oh cool discord does diffs how do
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
mad ty
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
❤️ markdown
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
oh ye it's pain
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
yeah i noticed that sadge
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
the pattern isn't right
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
this'd be the more correct usage
public class ContentfulClient
{
// nit: if these are just for the client maybe ContentfulClientOptions
private readonly ContentfulOptions _options;
private HttpClient _client;

public ContentfulClientBase(HttpClient client, ContentfulOptions options)
{
_client = client;
_options = options;
}
}

public class ContentfulManagementService
{
private ContentfulClient _client;

public ContentfulManagementService(ContentfulClient client)
{
_client = client
}
}
public class ContentfulClient
{
// nit: if these are just for the client maybe ContentfulClientOptions
private readonly ContentfulOptions _options;
private HttpClient _client;

public ContentfulClientBase(HttpClient client, ContentfulOptions options)
{
_client = client;
_options = options;
}
}

public class ContentfulManagementService
{
private ContentfulClient _client;

public ContentfulManagementService(ContentfulClient client)
{
_client = client
}
}
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
note the service getting the HTTP client in OP's example too
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
ye ye but like usually client is for wrapping the calls + serilization/deserilization and then the service handles business logic and orchestration
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
Ye for sure
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
Ye 🙂
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
I've seen that pattern in a few places and it makes me sadcat
Unknown User
Unknown User6mo ago
Message Not Public
Sign In & Join Server To View
Gramore
Gramore6mo ago
true and real but c# is a wonderful language that lets you do all kinds of interesting things