Wildcat in AddRazorPagesOptions Conventions.AddPageRoute - razor

I have this code:
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddRazorPagesOptions(options => {
options.Conventions.AddPageRoute("/Index", "Index.html");
options.Conventions.AddPageRoute("/rt", "rt.html");
});
}
Is it possible instead of writing each page, have one wildcat route like this?
options.Conventions.AddPageRoute("/*", "/{*.html}");

There is no built-in way to add such wildcard route. However you could achieve it with simple page route convention (implementation of IPageRouteModelConvention). Here is a working sample:
public class HtmlExtensionPageRouteModelConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var selectorCount = model.Selectors.Count;
for (var i = 0; i < selectorCount; ++i)
{
var attributeRouteModel = model.Selectors[i].AttributeRouteModel;
if (String.IsNullOrEmpty(attributeRouteModel.Template))
{
continue;
}
attributeRouteModel.SuppressLinkGeneration = true;
model.Selectors.Add(new SelectorModel
{
AttributeRouteModel = new AttributeRouteModel
{
Template = $"{attributeRouteModel.Template}.html",
}
});
}
}
}
Configuration:
public void ConfigureServices(IServiceCollection services)
{
services
.AddMvc()
.AddRazorPagesOptions(options => {
options.Conventions.Add(new HtmlExtensionPageRouteModelConvention());
});
}
Sample Project on GitHub

Related

How do I access a method that's in another method that's in a class in ECMA6Script?

How do I declare the method getYellowCycle() so that the variable game can access it? getYellowCycle is a method that's in another method called newGame(), that's in a class called model.game.
Here is where the method should be called.
let game = model.Game.newGame();
expect(game.getYellowCycle().getX()).to.equal(50);
Here is the class model.game
model.Game = class {
newGame() {
}
};
getYellowCycle() should go in newGame()
Something like this:
const model = {};
model.Game = class {
newGame() {
return {
getYellowCycle() {
return {
getX() {
console.log("In getX");
return 50;
}
};
}
};
}
};
const game = (new model.Game()).newGame();
console.log(game.getYellowCycle().getX());

Observable collection in MVVMLIght doesn't upadate UI

I have a ViewModel extending Galasoft.MvvmLight.ViewModelBase. In it i have this:
public ObservableCollection<Association> Delegation { get; set; }
private async void LoadDelegations()
{
Delegation.Clear();
var delegations = await NetworkManager.GetDelegations();
if(delegations== null)
{
return;
}
for (int i = 0;i< delegations.Count;i++)
{
Delegation.Add(delegations[i]);
}
}
private async void RemoveDelegation(string delegationId)
{
var response = await NetworkManager.RemoveDelegation(delegationId);
if (response.Result)
{
int i;
for (i = 0; i < Delegation.Count; i++)
{
if (Delegation[i].Id == delegationId) break;
}
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Delegation.RemoveAt(i);
});
}
}
This property is bound to a ListView:
<ListView ItemTemplate="{StaticResource AssociationTemplate}"
ItemsSource="{Binding Delegation}"/>
My problem is that LoadDelegation update the UI only sometimes, instead the RemoveDelegation never update the UI.
What am I doing wrong?
I am not sure about the MVVM-Light procedure but in the MVVM pattern, The issue here would be that you are using auto-implemented property. So the auto-implemented properties do not raise the INotifyPropertyChanged event. You can simply change the Auto-Implemented property of Delegation. You can change it to a full property by `private ObservableCollection delegation;
public ObservableCollection<Association> Delegation
{
get { return delegation; }
set { delegation = value; RaisePropertyChanged("Delegation")}
}`
While RaisePropertyChanged is the method that's called as soon as the property changes and lets the view know about it. And as MVVM-Light simply provides the base class which implements the INotifyPropertyChanged interface

Topshelf TimeoutException

I'm trying to use Topshelf Framework to create a windows service. But when i try to start the service, there is this exception :
" The service failed to start... System.Service.Process.TimeoutException : the waiting period has expired and the operation has not been completed"
This is my code :
public class MyService : ServiceControl
{
private System.Timers.Timer _timer;
public void MyService()
{
_timer = new System.Timers.Timer(10);
_timer.AutoReset = false;
_timer.Elapsed += new ElapsedEventHandler(TimerOnElapsed);
}
private void TimerOnElapsed(object source, ElapsedEventArgs e)
{
//all the operation to do at the startup
}
public bool Start(HostControl hostControl)
{
_timer.Start();
return true;
}
public bool Stop(HostControl hostControl)
{
_timer.Stop();
return true;
}
}
Thanks for any help :)
There are several issues I notice:
The current code would make the timer fire only once (you have AutoReset = false)
with TopShelf, the MyService class should look like this:
using System.Timers;
using Topshelf;
namespace TopShelfTestService
{
public class MyService
{
private System.Timers.Timer _timer;
public MyService()
{
_timer = new System.Timers.Timer(10);
_timer.AutoReset = true;
_timer.Elapsed += new ElapsedEventHandler(TimerOnElapsed);
}
private void TimerOnElapsed(object source, ElapsedEventArgs e)
{
//all the operation to do at the startup
}
public bool Start(HostControl hostControl)
{
_timer.Start();
return true;
}
public bool Stop(HostControl hostControl)
{
_timer.Stop();
return true;
}
}
}
and the console app/ Program.cs will look like so:
using Topshelf;
namespace TopShelfTestService
{
class Program
{
static void Main(string[] args)
{
HostFactory.Run(x =>
{
x.Service<MyService>(s =>
{
s.ConstructUsing(name => new MyService());
s.WhenStarted((tc, hostControl) => tc.Start(hostControl));
s.WhenStopped((tc, hostControl) => tc.Stop(hostControl));
});
x.RunAsLocalSystem();
x.SetDescription("Sample Topshelf Host"); //7
x.SetDisplayName("Test Service with TopShelf"); //8
x.SetServiceName("TopShelfTestService");
});
}
}
}

LocalSettings and background tasks WP 8.1

How to change values in Windows.Storage.ApplicationData.Current.LocalSettings with background task. I use such code like back ground task:
namespace MainTask
{
public sealed class Task :IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();
var storage = Windows.Storage.ApplicationData.Current.LocalSettings;
int i = (int)storage.Values["var"];
i++;
storage.Values["val"] = i;
_deferral.Complete();
}
}
}
Background task started and there is in livecycle events in debugger and it reads the storage. But Values["val"] does not change.
namespace MainTask
{
public sealed class Task :IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
BackgroundTaskDeferral _deferral = taskInstance.GetDeferral();
var storage = Windows.Storage.ApplicationData.Current.LocalSettings;
int i = (int)storage.Values["var"];
i++;
storage.Values.Remove("val");
storage.Values.Add("val", i);
_deferral.Complete();
}
}
}

Binding views to ICommand.CanExecute

Is it somehow possible to bind view properties to ICommand.CanExecute?
I'd for example like to be able to do something like this in a touch view:
this
.CreateBinding(SignInWithFacebookButton)
.For(b => b.Enabled)
.To((SignInViewModel vm) => vm.SignInWithFacebookCommand.CanExecute)
.Apply();
I've already read How to use CanExecute with Mvvmcross, but unfortunately it skips the questions and instead just proposes another implementation.
One way of doing this is to use your own custom button inheriting from UIButton.
For Android, I've got an implementation of this to hand - it is:
public class FullButton : Button
{
protected FullButton(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
Click += OnClick;
}
public FullButton(Context context) : base(context)
{
Click += OnClick;
}
public FullButton(Context context, IAttributeSet attrs) : base(context, attrs)
{
Click += OnClick;
}
public FullButton(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
{
Click += OnClick;
}
private IDisposable _subscription;
private object _commandParameter;
public object CommandParameter
{
get { return _commandParameter; }
set
{
_commandParameter = value;
UpdateEnabled();
}
}
private ICommand _command;
public ICommand Command
{
get { return _command; }
set
{
if (_subscription != null)
{
_subscription.Dispose();
_subscription = null;
}
_command = value;
if (_command != null)
{
var cec = typeof (ICommand).GetEvent("CanExecuteChanged");
_subscription = cec.WeakSubscribe(_command, (s, e) =>
{
UpdateEnabled();
});
}
UpdateEnabled();
}
}
private void OnClick(object sender, EventArgs eventArgs)
{
if (Command == null)
return;
if (Command.CanExecute(CommandParameter))
Command.Execute(CommandParameter);
}
private void UpdateEnabled()
{
Enabled = ShouldBeEnabled();
}
private bool ShouldBeEnabled()
{
if (_command == null)
return false;
return _command.CanExecute(CommandParameter);
}
}
and this can be bound as:
<FullButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Show Detail"
local:MvxBind="Command ShowDetailCommand; CommandParameter CurrentItem" />
For iOS, I'd expect the same type of technique to work... inheriting from a UIButton and using TouchUpInside instead of Click - but I'm afraid I don't have this code with me at the moment.