ArgumentNullException when invoking RenderComponent with Action - razor-components

I am trying to test a custom Razor component with an EventBack parameter:
#code {
[Parameter]
public EventCallback OnClick { get; set; }
}
I am using bUnit with xUnit to try to test EventCallback. Here's my test method:
public void TestOnClickEvent()
{
void TestOnClick()
{
Assert.True(true);
}
IRenderedComponent<CSInput> component =
RenderComponent<CSInput>(
builder => builder.Add(
instanceOfCSInput => instanceOfCSInput.OnClick,
TestOnClick));
component.Find("input").Click();
}
When I tried to run the test, I get an ArgumentNullException from RenderComponent(), but I have no idea what could it be since everything is all in lambda.

Apparently, the location function is the issue. I replace the call to the local function with another lambda and it works!
IRenderedComponent<CSInput> component =
RenderComponent<CSInput>(
builder => builder.Add(
instanceOfCSInput => instanceOfCSInput.OnClick,
() => Assert.True(true)));

Related

Cannot resolve parameter 'MediatR.ServiceFactory serviceFactory' (MediatR with Autofac)

I'm attempting to run MediatR with Autofac in .NET Framework 4.6.2.
My registration:
public class MediatorModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof(IMediator ).Assembly).AsImplementedInterfaces();
builder.RegisterType<HealthCheckQueryHandler>().As<IRequestHandler<HealthCheckQuery, HttpStatusCode>>();
}
}
My controller:
[RoutePrefix("api/v1/healthcheck")]
public class HealthCheckController : ApiController
{
private readonly IMediator _mediator;
public HealthCheckController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
[Route("")]
public async Task<HttpStatusCode> Get()
{
var query = new HealthCheckQuery();
var result = await _mediator.Send(query);
return result;
}
}
When I try to hit this api method, I receive the following error:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MediatR.Mediator' can be invoked with the available services and parameters:\r\nCannot resolve parameter 'MediatR.ServiceFactory serviceFactory' of constructor 'Void .ctor(MediatR.ServiceFactory)
The wiki (https://github.com/jbogard/MediatR/wiki) asks us to register SingleInstanceFactory and MultiInstanceFactory. But Visual Studio is not able to resolve either of these symbols.
How can I resolve this to get MediatR working with Autofac?
I know this is an old post, but in case anyone else googles for this.
You're missing registering the ServiceFactory instance.
builder.Register<ServiceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => c.Resolve(t);
});
Taken from here: MediatR Examples
I assume you are using Mediatr v3.0.x.
You are missing the registrations for the SingleInstanceFactory and MultiInstanceFactory as here below.
builder.Register<SingleInstanceFactory>(ctx => {
IComponentContext c = ctx.Resolve<IComponentContext>();
return type => {
Object o;
return c.TryResolve(type, out o) ? o : null;
};
});
builder.Register<MultiInstanceFactory>(ctx => {
IComponentContext c = ctx.Resolve<IComponentContext>();
return type => (IEnumerable<Object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(type));
});

Why am I getting error: "Cannot access disposed object" in .net core 2 with EF and AutoFac?

First the error:
Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and
then later trying to use the same context instance elsewhere in your
application. This may occur if you are calling Dispose() on the
context, or wrapping the context in a using statement. If you are
using dependency injection, you should let the dependency injection
container take care of disposing context instances.
Object name: 'MemberContext'.
I have 3 projects, Domain, API and WebSPA app.
Domain has 2 modules, DomainModule and MediatorModule
public class DomainModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(MemberContext).Assembly)
.AsImplementedInterfaces()
.InstancePerLifetimeScope(); // via assembly scan
builder.RegisterType<MemberContext>().AsSelf()
.InstancePerLifetimeScope(); // or individually
}
}
public class MediatorModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
// enables contravariant Resolve() for interfaces with single contravariant ("in") arg
builder
.RegisterSource(new ContravariantRegistrationSource());
// mediator itself
builder
.RegisterType<Mediator>()
.As<IMediator>()
.InstancePerLifetimeScope();
// request handlers
builder
.Register<SingleInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t =>
{
object o;
return c.TryResolve(t, out o) ? o : null;
};
})
.InstancePerLifetimeScope();
// notification handlers
builder
.Register<MultiInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>) c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
})
.InstancePerLifetimeScope();
}
}
In API project I have also 2 modules, ApplicationModule and again MediatorModule same as the one above.
public class ApplicationModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
.AsImplementedInterfaces()
.InstancePerLifetimeScope(); // via assembly scan
builder.RegisterType<MemberContext>().AsSelf().InstancePerLifetimeScope(); // or individually
}
}
No, when I debug I can see that member context gets newed up on each request, yet on second request, it throws above error. To make sure I am not going crazy, I modified constructor of dbcontext to create an id for context so i can verify they are different. What am I doing wrong?
public MemberContext(DbContextOptions<MemberContext> options) : base(options)
{
MemberContextId = Guid.NewGuid();
Console.WriteLine("member context created: " + MemberContextId);
}
Here is the startup in API
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
// .AllowCredentials()
);
});
services.AddMvc()
.AddControllersAsServices();//Injecting Controllers themselves thru DI
//For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
AddSwaggerGen(services);
//var connection = Configuration["ConnectionString"];
//services.AddDbContext<MemberContext>(options => options.UseSqlServer(connection),ServiceLifetime.Scoped);
services.AddEntityFrameworkSqlServer()
.AddDbContext<MemberContext>(options =>
{
options.UseSqlServer(Configuration["ConnectionString"]
//,sqlServerOptionsAction: sqlOptions =>
//{
// sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
// sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
//}
);
},
ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
);
var container = new ContainerBuilder();
container.Populate(services);
container.RegisterAssemblyModules(typeof(VIN.Members.Domain.Entities.Member).Assembly,
typeof(Startup).Assembly);
return new AutofacServiceProvider(container.Build());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//NOTE: must be before UseMVC !!!
app.UseCors("CorsPolicy");
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
}
private void AddSwaggerGen(IServiceCollection services)
{
services.AddSwaggerGen(options =>
{
options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
{
Title = "VIN Members HTTP API",
Version = "v1",
Description = "Members Service HTTP API",
TermsOfService = "Terms Of Service"
});
});
}
}
UPDATE:
What I am trying to do is delete a record. On client side code looks like this
onDelete(item: IMember) {
//TODO: replace this with dialog service component
if (window.confirm('Are sure you want to delete this member?')) {
//put your delete method logic here
this.service.deleteMember(item).subscribe(x => {
this.getMembers();
});
}
}
this delete request gets mapped to a controller that passes it to mediator
Controller
// DELETE api/members/5
[HttpDelete("{id}")]
public void Delete(Guid id)
{
var command = new DeleteMember.Command(id);
_mediator.Send(command).ConfigureAwait(false);
}
and finally handler
public class DeleteMember
{
public class Command : IRequest
{
public Command(Guid memberId)
{
Guard.NotNull(memberId, nameof(memberId));
MemberId = memberId;
}
public Guid MemberId { get; }
}
public class Handler : AsyncRequestHandler<Command>
{
private MemberContext _context;
public Handler(MemberContext context)
{
_context = context;
Console.WriteLine("Delete member context: " + context.MemberContextId);
}
protected override async Task HandleCore(Command cmd)
{
try
{
var member = await _context.FindAsync<Member>(cmd.MemberId);//.ConfigureAwait(false);
// if (member != null)
//// {
_context.Remove(member);
await _context.SaveChangesAsync().ConfigureAwait(false);
// }
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
}
As you can see there is no code that disposes that context. Scratching my head.
See this commented out check for member if null. That was throwing error as well, I commented it out just to see what will happen, and now it throws as SaveChangesAsync.
As request completes, context gets disposed. Since command handler uses SaveChangesAsync(), context is disposed before save completes. Culprit is controller method :). It should be async as well.
[HttpDelete("{id}")]
public async Task Delete(Guid id)
{
var command = new DeleteMember.Command(id);
await _mediator.Send(command).ConfigureAwait(false);
}
Your DbContext is scoped, meaning that Dependency Injection will return the same DbContext object every time one is asked for within the same HTTP request (in the case of ASP.NET).
That means that you should not be calling Dispose on your DbContext (otherwise that same object can't be used a second time). That seems to be what is happening to you, intentionally or not.
That does mean you should not be using using with it. Are you using using anywhere in your code against your DbContext?
I don't think you showed the line where the Exception is being thrown.
Update:
Try overriding Dispose in your MemberContext class. Something like this:
public override void Dispose() {
base.Dispose();
}
But just set a breakpoint there. When it breaks (if it does) check the stack trace and see what called it.
This can also be caused by having async void instead of async Task within WebAPI in my experience.

Dialog interaction requests using IObservable

I'm using reactive programming to build an MVVM app and am trying to figure out how my view model can raise a question and wait for a dialog to prompt the user for an answer.
For example, when the user clicks a Rename button I want a dialog to pop up that allows the user to change the text. My approach is for the view model to expose an IObservable<string> property. Code-behind in the View listens for emitted values and might display a UWP ContentDialog. If the user changes the text and clicks OK, code in that dialog would call ReportResult(string newText) on view model. I've got some code below to show how it works. Two questions:
Is this a reasonable approach for collecting information from the user?
Also, I've got two subtly different approaches for building this and don't know which is better.
interface IServiceRequest<TSource, TResult> : ISubject<TResult, TSource> { }
// Requests for information are just 'passed through' to listeners, if any.
class ServiceRequestA<TSource, TResult> : IServiceRequest<TSource, TResult>
{
IObservable<TSource> _requests;
Subject<TResult> _results = new Subject<TResult>();
public ServiceRequestA(IObservable<TSource> requests)
{
_requests = requests;
}
public IObservable<TResult> Results => _results;
public void OnCompleted() => _results.OnCompleted();
public void OnError(Exception error) => _results.OnError(error);
public void OnNext(TResult value) => _results.OnNext(value);
public IDisposable Subscribe(IObserver<TSource> observer) => _requests.Subscribe(observer);
}
// Requests for information are 'parked' inside the class even if there are no listeners
// This happens when InitiateRequest is called. Alternately, this class could implement
// IObserver<TSource>.
class ServiceRequestB<TSource, TResult> : IServiceRequest<TSource, TResult>
{
Subject<TSource> _requests = new Subject<TSource>();
Subject<TResult> _results = new Subject<TResult>();
public void InitiateRequest(TSource request) => _requests.OnNext(request);
public IObservable<TResult> Results => _results;
public void OnCompleted() => _results.OnCompleted();
public void OnError(Exception error) => _results.OnError(error);
public void OnNext(TResult value) => _results.OnNext(value);
public IDisposable Subscribe(IObserver<TSource> observer) => _requests.Subscribe(observer);
}
class MyViewModel
{
ServiceRequestA<string, int> _serviceA;
ServiceRequestB<string, int> _serviceB;
public MyViewModel()
{
IObservable<string> _words = new string[] { "apple", "banana" }.ToObservable();
_serviceA = new ServiceRequestA<string, int>(_words);
_serviceA
.Results
.Subscribe(i => Console.WriteLine($"The word is {i} characters long."));
WordSizeServiceRequest = _serviceA;
// Alternate approach using the other service implementation
_serviceB = new ServiceRequestB<string, int>();
IDisposable sub = _words.Subscribe(i => _serviceB.InitiateRequest(i)); // should dispose later
_serviceB
.Results
.Subscribe(i => Console.WriteLine($"The word is {i} characters long."));
WordSizeServiceRequest = _serviceB;
}
public IServiceRequest<string, int> WordSizeServiceRequest { get; set; }
// Code outside the view model, probably in the View code-behind, would do this:
// WordSizeServiceRequest.Select(w => w.Length).Subscribe(WordSizeServiceRequest);
}
Based on comments from Lee Campbell, here is a different approach. Maybe he'll like it better? I'm actually not sure how to build the IRenameDialog. Before it was just a bit of code-behind in the View.
public interface IRenameDialog
{
void StartRenameProcess(string original);
IObservable<string> CommitResult { get; }
}
public class SomeViewModel
{
ObservableCommand _rename = new ObservableCommand();
BehaviorSubject<string> _name = new BehaviorSubject<string>("");
public SomeViewModel(IRenameDialog renameDialog,string originalName)
{
_name.OnNext(originalName);
_rename = new ObservableCommand();
var whenClickRenameDisplayDialog =
_rename
.WithLatestFrom(_name, (_, n) => n)
.Subscribe(n => renameDialog.StartRenameProcess(n));
var whenRenameCompletesPrintIt =
renameDialog
.CommitResult
.Subscribe(n =>
{
_name.OnNext(n);
Console.WriteLine($"The new name is {n}");
};
var behaviors = new CompositeDisposable(whenClickRenameDisplayDialog, whenRenameCompletesPrintIt);
}
public ICommand RenameCommand => _rename;
}
Hmm.
The first block of code looks like a re-implementation of IObservable<T>, actually I think event worse ISubject<T>, so that raises alarm bells.
Then the MyViewModel class does other things like pass IObservable<string> as a parameter (Why?), create subscriptions (side effects) in the constructor, and expose a Service as a public property. You also metion having code in your view code behind, which is often a code-smell in MVVM too.
I would suggest reading up on MVVM (solved problem for 10yrs) and havnig a look at how other Client applications use Rx/Reactive programming with MVVM (solved problem for ~6yrs)
Lee shamed me into coming up with a better solution. The first and best turned out to be very simple. I pass into the constructor one of these:
public interface IConfirmationDialog
{
Task<bool> Show(string message);
}
Inside my view model, I can do something like this...
IConfirmationDialog dialog = null; // provided by constructor
_deleteCommand.Subscribe(async _ =>
{
var result = await dialog.Show("Want to delete?");
if (result==true)
{
// delete the file
}
});
Building a ConfirmationDialog wasn't hard. I just create one of these in the part of my code that creates view models and assigns them to views.
public class ConfirmationDialogHandler : IConfirmationDialog
{
public async Task<bool> Show(string message)
{
var dialog = new ConfirmationDialog(); // Is subclass of ContentDialog
dialog.Message = message;
var result = await dialog.ShowAsync();
return (result == ContentDialogResult.Primary);
}
}
So the solution above is pretty clean; dependencies my view model needs are provided in the constructor. Another approach similar to what Prism and ReactiveUI do is one where the ViewModel is constructed without the dependency it needs. Instead there is a bit of code-behind in the view to fill in that dependency. I don't need to have multiple handlers, so I just have this:
public interface IInteractionHandler<TInput, TOutput>
{
void SetHandler(Func<TInput, TOutput> handler);
void RemoveHandler();
}
public class InteractionBroker<TInput, TOutput> : IInteractionHandler<TInput, TOutput>
{
Func<TInput, TOutput> _handler;
public TOutput GetResponse(TInput input)
{
if (_handler == null) throw new InvalidOperationException("No handler has been defined.");
return _handler(input);
}
public void RemoveHandler() => _handler = null;
public void SetHandler(Func<TInput, TOutput> handler) => _handler = handler ?? throw new ArgumentNullException();
}
And then my ViewModel exposes a property like this:
public IInteractionHandler<string,Task<bool>> Delete { get; }
And handles the delete command like this:
_deleteCommand.Subscribe(async _ =>
{
bool shouldDelete = await _deleteInteractionBroker.GetResponse("some file name");
if (shouldDelete)
{
// delete the file
}
});

Laravel redirect to post method

To stay basic I would like to create a bookmark app
I have a simple bookmarklet
javascript:location.href='http://zas.dev/add?url='+encodeURIComponent(location.href)
I created a rest controller
<?php
use zas\Repositories\DbLinkRepository;
class LinksController extends BaseController {
protected $link;
function __construct(DbLinkRepository $link) {
$this->link=$link;
// ...
//$this->beforeFilter('auth.basic', array('except' => array('index', 'show', 'store')));
// ...
}
public function index()
{
//return Redirect::to('home');
}
public function create()
{
}
public function store()
{
return 'hello';
//$this->link->addLink(Input::get('url'));
//return Redirect::to(Input::get('url'));
}
public function show($id)
{
//$url = $this->link->getUrl($id);
//return Redirect::to($url);
}
public function edit($id)
{
}
public function update($id){
}
public function destroy($id){
}
}
in the routes.php, I created a ressource
Route::resource('links','LinksController');
and as I want to redirect /add to the store method I added
Route::get('/add',function(){
return Redirect::action('LinksController#store');
});
but it never display the hello message, in place it redirects me to
http://zas.dev/links
I also tried with
return Redirect::route('links.store');
without much success
thanks for your help
Ok I now get what you are trying to do. This will work:
Route::get('add', 'LinksController#store');
Remove:
Route::resource('links','LinksController');
and remove:
Route::get('/add',function(){
return Redirect::action('LinksController#store');
});
Sorry it took so long!
The problem is that once you Redirect::, you loose all the Input values, so you should manually give them to your controller when you do the redirect, like so :
Redirect::route('links.store', ["url" => Input::get("url")]);
Finally add an $url parameter to your store method to receive the value we give it in the previous method, like this :
public function store($url) {
$this->link->addLink($url);
return Redirect::to($url);
}

Error with Invoke method in a domainservice class

i'm new with silverlight/ria and i have a problem wath i don't understand.
I have the following code in my domain services class
[EnableClientAccess()]
[KnownType(typeof(ModeleEmailEa))]
[KnownType(typeof(ModeleSmsEa))]
public class EAEMailDomainService : DomainService
{
#region ModeleEnvoiEa CRUD
[Query()]
public IQueryable<ModeleEnvoiEa> SelectAllModeleEnvoiEa()
{
ModeleEnvoiEaSrv modeleService = new ModeleEnvoiEaSrv();
return modeleService.GetList<ModeleEnvoiEa>();
}
[Update]
public void UpdateModeleEnvoiEa(ModeleEnvoiEa modele)
{
ModeleEnvoiEaSrv modeleService = new ModeleEnvoiEaSrv();
modeleService.Update(modele);
}
[Insert]
public void InsertModeleEnvoiEa(ModeleEnvoiEa modele)
{
ModeleEnvoiEaSrv modeleService = new ModeleEnvoiEaSrv();
modeleService.Insert(modele);
}
[Delete]
public void DeleteModeleEnvoiEa(ModeleEnvoiEa modele)
{
ModeleEnvoiEaSrv modeleService = new ModeleEnvoiEaSrv();
modeleService.Delete(modele);
}
[Invoke]
public void Test(int valeur)
{
//Do something
}
#endregion
And this code in my Silverlight application
Context.Test(2, action =>
{
// Do something
}, null);
The function SelectAll, Update, Delete , Insert work's fine but the 'Test' function generated the following error:
an attempt was made to load a program
with an incorrect format
any ideas ?
I have found that if i write the function invocation like this it's works
Context.Test(2,new System.Action<InvokeOperation<Int>>(ModeleEnvoiEa_Completed),null);
}
void ModeleEnvoiEa_Completed(InvokeOperation invoke)
{
// Do something
}
but if i use a lambda expression like this, i have an error, why ?
Context.Test(2, action =>
{
// This code generate an error
// an attempt was made to load a program with an incorrect format
}, null);