Call a method in a CORE Razor Page from a ViewModel - razor-pages

My Razor Page
public class IndexModel : BaseModel {
public void OnGet() {
BaseModelMethod();
}
public void LocalMethod() {}
}
calls a method in the base ViewModel
public class BaseModel : PageModel {
public void BaseModelMethod() {
// Do stuff
}
}
Is there a way to call back to the instance of LocalMethod in the calling Razor Page?

You have to define the function as a virtual function. Your BaseModel has to have the following form:
public class BaseModel : PageModel
{
public void BaseModelMethod()
{
LocalMethod();
}
public virtual void LocalMethod()
{
}
}
As you can see I creted the virtual function so that we will know what we kind of method we will call.
Now we can define our own version of LocalMethod like this:
public class IndexModel : BaseModel
{
public void OnGet()
{
BaseModelMethod();
}
public override void LocalMethod()
{
base.LocalMethod();
}
}

Related

How to inherits a BaseRazorPage in Razor page

In razor engine way, I can define a BaseRazorPage for all razor views
public abstract class BaseRazorPage<TModel> : RazorPage<TModel>
{
protected BaseRazorPage()
{
}
protected virtual string L(string name)
{
return XXX.Localization.L.Text[name];
}
......
}
Use it in _viewImports.cshtml
#inherits BaseRazorPage<TModel>
Then I can use the L function to do mutiple language in views:
#L("Hello word!")
How can I implement same function in Razor page way? Or is there an alternative way to do this?
The razor page can't inherits any class.
A simple solution would be to create an extension for the PageModel class.
public static class PageModelExtensions
{
public static string L(this PageModel pageModel, string name)
{
// return a new value. put your logic here
return name + "_result";
}
}
Now we can use the L method as a member function.
public class IndexModel : PageModel
{
public void OnGet()
{
string value = this.L("test");
}
}
Or we can use the L method in the view like this
#page
#model IndexModel
#{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>#Model.L("test")</p>
</div>
I hope this helps.
UPDATE
If you want to have a base class with your common methods the following example is what you want.
public class MyPageModel : PageModel
{
public string L(string name)
{
return "sample";
}
}
And your razor page class will look like this.
public class IndexModel : MyPageModel
{
public void OnGet()
{
string value = this.L("test");
}
}
In case you want to inject an object in your base class then you base class should look like this.
public class MyPageModel : PageModel
{
private readonly ApplicationDbContext context;
public MyPageModel(ApplicationDbContext context)
{
this.context = context;
}
public string L(string name)
{
return "sample";
}
}
And the Razor page will look like this
public class IndexModel : MyPageModel
{
private readonly ApplicationDbContext context;
public IndexModel(ApplicationDbContext context)
: base(context)
{
this.context = context;
}
public void OnGet()
{
string value = this.L("test");
}
}

Guice - Dynamically selecting provider based on external parameter

In guice, Is there a way to select particular implementation for binding based on some external parameter
Eg:
public interface Service {
void sendMessage()
}
class EmailService implements Service {
public EmailService() { }
#Override
void sendMessage() {
println "Sending email..."
}
}
class SMSService implements Service {
public EmailService() { }
#Override
void sendMessage() {
println "Sending sms..."
}
}
class Client {
private Service service
#Inject
Client(Service service) {
this.service = service
}
public void send() {
service.sendMessage()
}
}
public class ServiceProvider implements Provider<Service> {
Service get() {
return new SMSService() //Select implementation here?
}
}
public class MyModule extends AbstractModule {
#Override
protected void configure() {
bind(Service.class).toProvider(ServiceProvider.class).in(Scopes.SINGLETON)
}
}
public static void main(String...args) {
Injector injector = Guice.createInjector(new MyModule())
Client c = injector.getInstance(Client.class)
c.send()
}
In the above example, I'm forced to select which provider to use in Provider get() method. If I want to make this more dynamic, say for example, based on user preference, is there a way to wait select the provider at runtime and have guice inject it?
For these kind of problems, guice offers the MapBinder:
public class SnacksModule extends AbstractModule {
protected void configure() {
MapBinder<String, Snack> mapbinder
= MapBinder.newMapBinder(binder(), String.class, Snack.class);
mapbinder.addBinding("twix").toInstance(new Twix());
mapbinder.addBinding("snickers").toProvider(SnickersProvider.class);
mapbinder.addBinding("skittles").to(Skittles.class);
}
}
With this binding, a Map can now be injected:
class SnackMachine {
#Inject
public SnackMachine(Map<String, Snack> snacks) { ... }
}
You can define all your services in advance, and than pick the concrete instance (or provider) from the map byconfigured value.

Is it possible to use Jax-WS with a Generic interface?

How to use a generic common Interface for Jax-WS ?
public interface IGenericWebService<T extends Record> {
#WebMethod
public List<T> listAll();
}
how to make it works without overriding the method ?
#WebService
public interface IWCustomerService extends IGenericWebService<Customer>{
/*
#WebMethod
public List<Customer> listAll(); */
}
Common implementation
public abstract class GenericWebService<T extends Record> implements IGenericWebService<T>{
protected static Log log = LogFactory.getLog(GenericWebService.class);
}
Customer Service
#WebService(endpointInterface="com.dev.bridge.iwservices.IWCustomerService")
#Service
public class WCustomerService extends GenericWebService<Customer> implements IWCustomerService{
#Autowired
private ICustomerService customerService;
public List<Customer> listAll() {
try {
return customerService.listAll();
} catch (CoreException e) {
log.error(e.getMessage(), e);
}
return new ArrayList<Customer>();
}
}

ServiceStack's Funq.Container not Newing-Up Properties

My service uses a utility class and that utility class has several public properties. Is there something special I need call to ensure these public properties are setup?
The service uses a ASP.NET host. Inside of Global.ASAX I have declared a new AppHostBase:
public class MyServiceHost : AppHostBase
{
public MyServiceHost() : base("My Service Host", typeof(ServiceLibrary).Assembly) {}
public override void Configure(Funq.Container container)
{
container.Register<IDbConnectionFactory>(dbConFactory);
container.RegisterAutoWired<UtilityLibrary>();
container.RegisterAutoWired<RepositoryLibrary>();
}
}
Within both my repository library and utility library is a main class. This may class receives the Container and registers more specific utilities and repositories:
public class UtilityLibrary
{
public UtilityLibrary(Funq.Container container)
{
container.RegisterAutoWired<WidgetAActions>();
container.RegisterAutoWired<WidgetBActions>();
}
}
In the example below, WidgetARepository was set in the constructor of the RepositoryLibrary class. The RepositoryLibrary class, which contains the WidgetARepository, was supplied to the Container in the Configure method of the AppHost (first snippet above). Even still, the WidgetARepository (below) is never set:
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
public WidgetA Get(string id)
{
var item = this.WidgetARepository.Get(id);
if (item == null) { return null; }
// Do something else
return item;
}
}
Must I manually call Resolve()? This seems like it would defeat the purpose of injection by doing this.
If you are using wanting to use the Funq Container Autowire IoC outside of the ServiceStack service then you need to call Container.AutoWire yourself to have the container inject the relevant dependencies. This call is made behind the scenes in the ServiceStack request pipeline.
For ServiceStack v4:
HostContext.Container.AutoWire(objectToPopulate);
For ServiceStack v3:
AppHostBase.Instance.Container.AutoWire(objectToPopulate);
I would typically add this call to the construtor method of the object I want populated with the injections. So in your case:
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
public WidgetAActions()
{
// (Substitute with v3 usage if required.)
HostContext.Container.AutoWire(this);
}
...
}
Hope this helps.
Edit: Have you considered having the container inject the corresponding repository to WidgetAActions's constructor?
container.RegisterAutoWired<WidgetAActions>(c => new WidgetAActions(c.Resolve<WidgetARepository>()));
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; private set; }
public WidgetAActions(WidgetARepository repository)
{
WidgetARepository = repository;
}
...
}
Edit: Or you could resolve and set the public property of your object to the repository and then you don't have to have a constructor:
container.RegisterAutoWired<WidgetAActions>(c =>
new WidgetAActions { WidgetARepository = c.Resolve<WidgetARepository>() }
);
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
...
}
Or you could call autowire at time of resolving WidgetAActions:
container.RegisterAutoWired<WidgetAActions>(c => {
var actions = new WidgetAActions();
container.AutoWire(actions); // All dependencies injected
return actions;
});
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
...
}

NServiceBus Configuration with Custom Container

I am trying to re-use the service registrations in an assembly that I use through a few services in my solution. I follow the example listed from the NServiceBus website to implement the solution. When following that, unless I add the IWantCustomInitialization interface, my Init method (and IoC container implementation) appears not to function. When I have that interface implemented, I get exceptions (listed in SO questions here and here). I can't seem to get it to work that there are no exceptions AND the dependencies in my MessageHandler are being populated properly. Here is my current EndpointConfig implementation.
[EndpointSLA("00:00:30")]
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, UsingTransport<Msmq>, INeedInitialization {
public void Init() {
Configure.With().ObjectBuilderAdapter();
}
}
public class ObjectBuilderAdapter : IContainer {
readonly IDependencyInjector injector;
public ObjectBuilderAdapter(IDependencyInjectionBuilder dependencyInjectionBuilder) {
injector = dependencyInjectionBuilder.Create(); //This method does all the common service registrations that I am trying to re-use
//injector.RegisterType<ExtractIncomingPrincipal, PrincipalExtractor>();
}
public void Dispose() {
injector.Dispose();
}
public object Build(Type typeToBuild) {
return injector.Resolve(typeToBuild);
}
public IContainer BuildChildContainer() {
return new ObjectBuilderAdapter(new DependencyInjectorBuilder());
}
public IEnumerable<object> BuildAll(Type typeToBuild) {
return injector.ResolveAll(typeToBuild);
}
public void Configure(Type component, DependencyLifecycle dependencyLifecycle) {
injector.RegisterType(component);
}
public void Configure<T>(Func<T> component, DependencyLifecycle dependencyLifecycle) {
injector.RegisterType(component);
}
public void ConfigureProperty(Type component, string property, object value) {
if (injector is AutofacDependencyInjector) {
((AutofacDependencyInjector)injector).ConfigureProperty(component, property, value);
} else {
Debug.WriteLine("Configuring {0} for property {1} but we don't handle this scenario.", component.Name, property);
}
}
public void RegisterSingleton(Type lookupType, object instance) {
injector.RegisterInstance(lookupType, instance);
}
public bool HasComponent(Type componentType) {
return injector.IsRegistered(componentType);
}
public void Release(object instance) { }
}
public static class Extensions {
public static Configure ObjectBuilderAdapter(this Configure config) {
ConfigureCommon.With(config, new ObjectBuilderAdapter(new DependencyInjectorBuilder()));
return config;
}
}
Note: When I use the INeedInitialization interface, I get the ComponentNotRegisteredException when it's looking for IStartableBus.
When you are trying to swap the built in container, then you need to implement IWantCustomInitialization in the same class that implements IConfigureThisEndpoint.
You can use your own container and register all your types in there and tell NSB to use that container.
For example:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization
{
public void Init()
{
var container = new ContainerBuilder().Build();
Configure.With()
.AutofacBuilder(container);
}
}

Resources