Xamarin.Forms How to save model to database without savebutton, Best practises - xamarin

My colleague and I want to create an application with some pages, where the user is allowed to change some settings. These settingspages do not have savebuttons. There is a main settingspage and two child settingspages. The settings should be persisted if the user navigates back from one of the three pages or the user makes some changes in one of the child pages.
The model is loaded in the OnAppearing() Method of the main settingspage. So we can not use OnDisappearing() Method of the childpages to save the model, because the sequence of these methods and Pushed() and Popped() of the navigationpage differs on each platform: forums.xamarin.com/discussion/21417/navigationpage-push-pop-event-sequence-different-across-platforms
Our solution at this time is to save the model in the setters of the properties of the childpages viewmodels. But that could not be best practise. So our question is: Are there any other solutions to solve this problem? What are the best practises for that problem?
Code:
public ReminderRepetitive ListViewSelectedItem
{
get { return _settingsEntity.ReminderRepetitive; }
set
{
if (!Equals(_settingsEntity.ReminderRepetitive, value))
{
_settingsEntity.ReminderRepetitive = value;
OnPropertyChanged("ListViewSelectedItem");
Save();
_navigation.PopAsync();
}
}
}
public void Save()
{
_businessLayer.UpdateSettings(_settingsEntity);
}

There are improvements to be made with your code.
You shouldn't do the navigation from a property - if you're going to be navigating away at least make that a method. That method should be async and you should await for the _navigation.PopAsync()
Even calling the Save() shouldn't be there. Consider what happens if an exception occurs while saving: duplicate keys, null fields etc are all possible. Then not only you won't Save but you won't PopAsync either and your ListViewSelectedItem = newItem will cause your selected item handler to blow up as well. And if you're going to have a property that also handles showing error messages you're definitely well inside MessyCode territory.
You can use the PropertyChanged on your model (ReminderRepetitive) and save immediately as soon as a property is changed.
It looks like you have a _businessLayer the whole business of saving or updating may belong there.
As a whole your question is pretty broad and can be treated as "opinion based". Next time try asking about specific parts of the code you're not sure about or cause errors - or use Code Review

Related

Xamarin Async Constructor

For my application I need to fetch some data asynchronously and do some initialization for each page. Unfortunately, a constructor does not allow me to make asynchronous calls. I followed this article and put all of my code into the OnAppearing method. However, since then I ran into multiple issues since each platform handles the event a little bit differently. For example, I have pages where you can take pictures, on iOS the OnAppearing is called again every time after the camera is closed while Android doesn't. It doesn't seem like a reliable method for my needs, which is also described here:
Calls to the OnDisappearing and OnAppearing overrides cannot be treated as guaranteed indications of page navigation. For example, on iOS, the OnDisappearing override is called on the active page when the application terminates.
I am searching for a method/way where I can perform my own initialization. The constructor would be perfect for that but I cannot perform anything asynchronously in there. Please do not provide me with any work arounds, I am searching for a solution that is the "recommended" way or maybe someone with a lot of experience can tell me what they are doing. (I also don't want to .Wait() or .Result as it will lock my app)
You can use Stephen Cleary's excellent NotifyTaskCompletion class.
You can read more how it works and what to do/don't in these cases in Microsoft's excellent Async Programming : Patterns for Asynchronous MVVM Applications: Data Binding. The highlights of this topics are:
Let’s walk through the core method
NotifyTaskCompletion.WatchTaskAsync. This method takes a task
representing the asynchronous operation, and (asynchronously) waits
for it to complete. Note that the await does not use
ConfigureAwait(false); I want to return to the UI context before
raising the PropertyChanged notifications. This method violates a
common coding guideline here: It has an empty general catch clause. In
this case, though, that’s exactly what I want. I don’t want to
propagate exceptions directly back to the main UI loop; I want to
capture any exceptions and set properties so that the error handling
is done via data binding. When the task completes, the type raises
PropertyChanged notifications for all the appropriate properties.
A sample usage of it:
public class MainViewModel
{
public MainViewModel()
{
UrlByteCount = new NotifyTaskCompletion<int>(
MyStaticService.CountBytesInUrlAsync("http://www.example.com"));
}
public NotifyTaskCompletion<int> UrlByteCount { get; private set; }
}
Here, the demo is about binding the returned asynchronous value to some bindable property, but of course you can you is without any return value (for simple data loading).
This may be too simple to say, but you CAN run asynchronous tasks in the constructor. Just wrap it in an anonymous Task.
public MyConstructor() {
Task.Run(async () => {
<Your code>
}
}
Be careful when doing this though as you can get into resource conflict issues if you accidentally open the page twice.
Another thing I like to do is use an _isInit flag, which indicates a first time use, and then never again.

Is it bad to use ViewModelLocator to Grab other VM's for use in another Vm?

I am using MVVM light and figured out since that the ViewModelLocator can be used to grab any view model and thus I can use it to grab values.
I been doing something like this
public class ViewModel1
{
public ViewModel1()
{
var vm2 = new ViewModelLocator().ViewModel2;
string name = vm2.Name;
}
}
This way if I need to go between views I can easily get other values. I am not sure if this would be best practice though(it seems so convenient makes me wonder if it is bad practice lol) as I know there is some messenger class thing and not sue if that is the way I should be doing it.
Edit
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<ViewModel1>();
SimpleIoc.Default.Register<ViewModel2>();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public ViewModel1 ViewModel1
{
get
{
return ServiceLocator.Current.GetInstance<ViewModel1 >();
}
}
Edit
Here is a scenario that I am trying to solve.
I have a view that you add price and store name to. When you click on the textbox for store name you are transferred to another view. This view has a textbox that you type the store you are looking for, as you type a select list get populated with all the possible matches and information about that store.
The user then chooses the store they want. They are transferred back to the view where they "add the price", now the store name is filled in also.
If they hit "add" button it takes the price, the store name, and the barcode(this came from the view BEFORE "add price view") and sends to a server.
So as you can see I need data from different views.
I'm trying to understand what your scenario is. In the MVVMlight forum, you added the following context to this question:
"I have some data that needs to be passed to multiple screens and possibly back again."
For passing data between VMs, I would also - as Matt above - use the Messenger class of MVVMLight as long as it is "fire and forget". But it is the "possibly back again" comment that sounds tricky.
I can imagine some scenarios where this can be needed. Eg. a wizard interface. In such a case I would model the data that the wizard is responsible for collecting and then bind all Views to the same VM, representing that model object.
But that's just one case.
So maybe if you could provide a little more context, I would be happy to try and help.
Yes, you can do this, in as much as the code will work but there is a big potential issue you may run into in the future.
One of the strong arguments for using the MVVM pattern is that it makes it easier to write code that can be easily tested.
With you're above code you can't test ViewModel1 without also having ViewModelLocator and ViewModel2. May be that's not too much of a bad thing in and of itself but you've set a precedent that this type of strong coupling of classes is acceptable. What happens, in the future, when you
From a testing perspective you would probably benefit from being able to inject your dependencies. This means passing, to the constructor--typically, the external objects of information you need.
This could mean you have a constructor like this:
public ViewModel1(string vm2Name)
{
string name = vm2Name;
}
that you call like this:
var vm1 = new ViewModel1(ViewModelLocator.ViewModel2.name);
There are few other issues you may want to consider also.
You're also creating a new ViewModelLocator to access one of it's properties. You probably already have an instance of the locator defined at the application level. You're creating more work for yourself (and the processor) if you're newing up additional, unnecessary instances.
Do you really need a complete instance of ViewModel2 if all you need is the name? Avoid creating and passing more than you need to.
Update
If you capture the store in the first view/vm then why not pass that (ID &/or Name) to the second VM from the second view? The second VM can then send that to the server with the data captured in the second view.
Another approach may be to just use one viewmodel for both views. This may make your whole problem go away.
If you have properties in 1 view or view model that need to be accessed by a second (or additional) views or view models, I'd recommend creating a new class to store these shared properties and then injecting this class into each view model (or accessing it via the locator). See my answer here... Two views - one ViewModel
Here is some sample code still using the SimpleIoc
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<IMyClass, MyClass>();
}
public IMyClass MyClassInstance
{
get{ return ServiceLocator.Current.GetInstance<IMyClass>();}
}
Here is a review of SimpleIOC - how to use MVVMLight SimpleIoc?
However, as I mentioned in my comments, I changed to use the Autofac container so that my supporting/shared classes could be injected into multiple view models. This way I did not need to instantiate the Locator to access the shared class. I believe this is a cleaner solution.
This is how I registered MyClass and ViewModels with the Autofac container-
var builder = new ContainerBuilder();
var myClass = new MyClass();
builder.RegisterInstance(myClass);
builder.RegisterType<ViewModel1>();
builder.RegisterType<ViewModel2>();
_container = builder.Build();
ServiceLocator.SetLocatorProvider(() => new AutofacServiceLocator(_container));
Then each ViewModel (ViewModel1, ViewModel2) that require an instance of MyClass just add that as a constructor parameter as I linked initially.
MyClass will implement PropertyChanged as necessary for its properties.
Ok, my shot at an answer for your original question first is: Yes, I think it is bad to access one VM from another VM, at least in the way it is done in the code example of this question. For the same reasons that Matt is getting at - maintainability and testability. By "newing up" another ViewModelLocator in this way you hardcode a dependency into your view model.
So one way to avoid that is to consider Dependency Injection. This will make your dependencies explicit while keeping things testable. Another option is to use the Messenger class of MVVMLight that you also mention.
In order to write maintainable and testable code in the context of MVVM, ViewModels should be as loosely coupled as possible. This is where the Messenger of MVVMLight can help. Here's a quote from Laurent on what Messenger class was intended for:
I use it where decoupled communication must take place. Typically I use it between VM and view, and between VM and VM. Strictly speaking you can use it in multiple places, but I always recommend people to be careful with it. It is a powerful tool, but because of the very loose coupling, it is easy to lose the overview on what you are doing. Use it where it makes sense, but don't replace all your events and commands with messages.
So, to answer the more specific scenario you mention, where one view pops up another "store selection" view and the latter must set the current store when returning back to the first view, this is one way to do it (the "Messenger way"):
1) On the first view, use EventToCommand from MVVMLight on the TextBox in the first view to bind the desired event (eg. GotFocus) to a command exposed by the view model. Could be eg. named OpenStoreSelectorCommand.
2) The OpenStoreSelectorCommand uses the Messenger to send a message, requesting that the Store Selector dialog should be opened. The StoreSelectorView (the pop-up view) subscribes to this message (registers with the Messenger for that type of message) and opens the dialog.
3) When the view closes with a new store selected, it uses the Messenger once again to publish a message that the current store has changed. The main view model subscribes to this message and can take whatever action it needs when it receives the message. Eg. update a CurrentStore property, which is bound to a field on the main view.
You may argue that this is a lot of messaging back and forth, but it keeps the view models and views decoupled and does not require a lot code.
That's one approach. That may be "old style" as Matt is hinting, but it will work, and is better than creating hard dependencies.
A service-based approach:
For a more service-based approach take a look at this recent MSDN Magazine article, written by the inventor of MVVMLight. It gives code examples of both approaches: The Messenger approach and a DialogService-based approach. It does not, however, go into details on how you get values back from a dialog window.
That issue is tackled, without relying on the Messenger, in this article. Note the IModalDialogService interface:
public interface IModalDialogService
{
void ShowDialog<TViewModel>(IModalWindow view, TViewModel viewModel, Action<TViewModel> onDialogClose);
void ShowDialog<TDialogViewModel>(IModalWindow view, TDialogViewModel viewModel);
}
The first overload has an Action delegate parameter that is attached as the event handler for the Close event of the dialog. The parameter TViewModel for the delegate is set as the DataContext of the dialog window. The end result is that the view model that caused the dialog to be shown initially, can access the view model of the (updated) dialog when the dialog closes.
I hope that helps you further!

wicket: how to update a component after AjaxLazyLoadPanel?

I have a page that has a status text label and a panel doing some DB query. since the query can take some time I am loading it using
add(new AjaxLazyLoadPanel("resultPanel")
{
#Override
public Component getLazyLoadComponent(String id) {
return new SearchResultPanel(id);
}
};
which works very well.
My question is how to update the status label which is outside of the resultPanel, to show the number of search results?
I was thinking along the lines of addComonent(target) but I don't have a target? am i off the track?
Well the SearchResultPanel might look like this:
public class SearchResultPanel extends Panel implements IHeaderContributor{
public SearchResultPanel(String id){
super(id);
....
}
public void renderHead(IHeaderResponse response){
response.renderOnDomReadyJavascript("alert('hello');");
}
}
Now when it is loaded it should throw out that javascript. Another way answered on stackoverflow previously (though I do not like it) is to use an AjaxSelfUpdatingTimerBehavior, which unless the javascript should be ran more then once I do not like, and still it is less elegant in my opinion.
Look here for their answer: Wicket: reload AjaxLazyLoadPanel automatically
You can always obtain the current request target using RequestCycle.get().getRequestTarget(), provided that there is an active request cycle, so in theory you could do that from your lazy-loaded component constructor, check if it is an Ajax target, and add the component if it is.
Another solution is to look at the source code of AjaxLazyLoadPanel and create your own component based on it. (It's really simple but as you can see if you look at the code, there's no way you can make it expose the request target. This isn't a very OO thing to do, but as all the important functionality is wrapped in the constructor, you have very little choice..
I would avoid having to tamper with Javascript, unless there's really no other way.
Happened to come across this post and I have something to add as well.
The AjaxLazyLoadPanel now has an overridable method called onComponentLoaded(Component, AjaxRequestTarget) which could also solve your problem.

Loose programming in high level languages, how, why and how much?

I'm writing my code in Haxe. This is quite irrelevant to the question though, as long as you keep in mind that it's a high level language and compareable with Java, ActionScript, JavaScript, C#, etc. (I'm using pseudocode here).
I'm going to work on a big project and am busy preparing now. For this question I'll create a small scenario though: a simple application which has a Main class (this one is executed when the application launches) and a LoginScreen class (this is basically a class that loads a login screen so that the user can login).
Typically I guess this would look like the following:
Main constructor:
loginScreen = new LoginScreen()
loginScreen.load();
LoginScreen load():
niceBackground = loader.loadBitmap("somebg.png");
someButton = new gui.customButton();
someButton.onClick = buttonIsPressed;
LoginScreen buttonIsPressed():
socketConnection = new network.SocketConnection();
socketConnection.connect(host, ip);
socketConnection.write("login#auth#username#password");
socketConnection.onData = gotAuthConfirmation;
LoginScreen gotAuthConfirmation(response):
if response == "success" {
//login success.. continue
}
This simple scenario adds the following dependencies and downsides to our classes:
Main will not load without LoginScreen
LoginScreen will not load without the custom loader class
LoginScreen will not load without our custom button class
LoginScreen will not load without our custom SocketConnection class
SocketConnection (which will have to be accessed by a lot of different classes in the future) has been set inside LoginScreen now, which is actually quite irrelevant from it, apart from the fact that the LoginScreen requires a socket connection for the first time
To solve these problems, I have been suggested to do "Event-Driven-Programming", or loose coupling. As far as I understand, this basically means that one has to make classes independent from each other and then bind them together in separate binders.
So question 1: is my view on it true or false? Does one have to use binders?
I heard Aspect Oriented Programming could help here. Unfortunately Haxe does not support this configuration.
However, I do have access to an event library which basically allows me to create a signaller (public var loginPressedSignaller = new Signaller()), to fire a signaller (loginPressedSignaller.fire()) and to listen to a signalller (someClass.loginPressedSignaller.bind(doSomethingWhenLoginPressed)).
So, with little further investigation I figured this would change my previous setup to:
Main:
public var appLaunchedSignaller = new Signaller();
Main constructor:
appLaunchedSignaller.fire();
LoginScreen:
public var loginPressedSignaller = new Signaller();
LoginScreen load():
niceBackground = !!! Question 2: how do we use Event Driven Programming to load our background here, while not being dependent on the custom loader class !!!
someButton = !!! same as for niceBackground, but for the customButton class !!!
someButton.onClick = buttonIsPressed;
LoginScreen buttonIsPressed():
loginPressedSignaller.fire(username, pass);
LoginScreenAuthenticator:
public var loginSuccessSignaller = new Signaller();
public var loginFailSignaller = new Signaller();
LoginScreenAuthenticator auth(username, pass):
socketConnection = !!! how do we use a socket connection here, if we cannot call a custom socket connection class !!!
socketConnection.write("login#auth#username#password");
This code is not finished yet, eg. I still have to listen for the server response, but you probably understand where I am getting stuck.
Question 2: Does this new structure make any sense? how should I solve the problems above mentioned in the !!! delimiters?
Then I heard about binders. So maybe I need to create a binder for each class, to connect everything together. Something like this:
MainBinder:
feature = new Main();
LoginScreenBinder:
feature = new LoginScreen();
MainBinder.feature.appLaunchedSignaller.bind(feature.load);
niceBackgroundLoader = loader.loadBitmap;
someButtonClass = gui.customButton();
etc... hopefully you understand what I mean. This post is getting a bit long so I have to wrap it up a bit.
Question 3: does this make any sense? Doesn't this make things unnecessarily complex?
Also, in the above "Binders" I only had to use classes which are instantiated once, eg. a login screen. What if there are multiple instances of a class, eg. a Player Class in a game of chess.
well, concerning the how, I would point out my 5 commandments to you. :)
For this question only 3 are really important:
single responsibility (SRP)
interface segregation (ISP)
dependency inversion (DIP)
Starting off with SRP, you have to ask yourself the question: "What is the responsibility of class X?".
The login screen is responsible for presenting an interface to the user to fill in and submit his login data. Thus
it makes sense for it to depend on the button class, because it needs the button.
it makes no sense it does all the networking etc.
First of all, you let's abstract the login service:
interface ILoginService {
function login(user:String, pwd:String, onDone:LoginResult->Void):Void;
//Rather than using signalers and what-not, I'll just rely on haXe's support for functional style,
//which renders these cumbersome idioms from more classic languages quite obsolete.
}
enum Result<T> {//this is a generic enum to return results from basically any kind of actions, that may fail
Fail(error:Int, reason:String);
Success(user:T);
}
typedef LoginResult = Result<IUser>;//IUser basically represent an authenticated user
From the point of view of the Main class, the login screen looks like this:
interface ILoginInterface {
function show(inputHandler:String->String->Void):Void;
function hide():Void;
function error(reason:String):Void;
}
performing login:
var server:ILoginService = ... //where ever it comes from. I will say a word about that later
var login:ILoginInterface = ... //same thing as with the service
login.show(function (user, pwd):Void {
server.login(user, pwd, function (result) {
switch (result) {
case Fail(_, reason):
login.error(reason);
case Success(user):
login.hide();
//proceed with the resulting user
}
});
});//for the sake of conciseness I used an anonymous function but usually, you'd put a method here of course
Now ILoginService looks a little titchy. But to be honest, it does all it needs to do. Now it can effectively be implemented by a class Server, that encapsulates all networking in a single class, having a method for each of the N calls your actual server provides, but first of all, ISP suggests, that many client specific interfaces are better than one general purpose interface. For the same reason ILoginInterface is really kept to its bare minimum.
No matter, how these two are actually implemented, you will not need to change Main (unless of course the interface changes). This is DIP being applied. Main doesn't depend on the concrete implementation, only on a very concise abstraction.
Now let's have some implementations:
class LoginScreen implements ILoginInterface {
public function show(inputHandler:String->String->Void):Void {
//render the UI on the screen
//wait for the button to be clicked
//when done, call inputHandler with the input values from the respective fields
}
public function hide():Void {
//hide UI
}
public function error(reason:String):Void {
//display error message
}
public static function getInstance():LoginScreen {
//classical singleton instantiation
}
}
class Server implements ILoginService {
function new(host:String, port:Int) {
//init connection here for example
}
public static function getInstance():Server {
//classical singleton instantiation
}
public function login(user:String, pwd:String, onDone:LoginResult->Void) {
//issue login over the connection
//invoke the handler with the retrieved result
}
//... possibly other methods here, that are used by other classes
}
Ok, that was pretty straight forward, I suppose. But just for the fun of it, let's do something really idiotic:
class MailLogin implements ILoginInterface {
public function new(mail:String) {
//save address
}
public function show(inputHandler:String->String->Void):Void {
//print some sort of "waiting for authentication"-notification on screen
//send an email to the given address: "please respond with username:password"
//keep polling you mail server for a response, parse it and invoke the input handler
}
public function hide():Void {
//remove the "waiting for authentication"-notification
//send an email to the given address: "login successful"
}
public function error(reason:String):Void {
//send an email to the given address: "login failed. reason: [reason] please retry."
}
}
As pedestrian as this authentication may be, from the point of view of the Main class,
this doesn't change anything and thus will work just as well.
A more likely scenario is actually, that your login service is on another server (possibly an HTTP server), that makes the authentication, and in case of success creates a session on the actual app server. Design-wise, this could be reflected in two separate classes.
Now, let's talk about the "..." I left in Main. Well, I'm lazy, so I can tell you, in my code you are likely to see
var server:ILoginService = Server.getInstance();
var login:ILoginInterface = LoginScreen.getInstance();
Of course, this is far from being the clean way to do it. The truth is, it's the easiest way to go and the dependency is limited to one occurrence, that can later be removed through dependency injection.
Just as a simple example for an IoC-Container in haXe:
class Injector {
static var providers = new Hash < Void->Dynamic > ;
public static function setProvider<T>(type:Class<T>, provider:Void->T):Void {
var name = Type.getClassName(type);
if (providers.exists(name))
throw "duplicate provider for " + name;
else
providers.set(name, provider);
}
public static function get<T>(type:Class<T>):T {
var name = Type.getClassName(type);
return
if (providers.exists(name))
providers.get(name);
else
throw "no provider for " + name;
}
}
elegant usage (with using keyword):
using Injector;
//wherever you would like to wire it up:
ILoginService.setProvider(Server.getInstance);
ILoginInterface.setProvider(LoginScreen.getInstance);
//and in Main:
var server = ILoginService.get();
var login = ILoginInterface.get();
This way, you practically have no coupling between the individual classes.
As to the question how to pass events between the button and the login screen:
this is just a matter of taste and implementation.
The point of event driven programming is that both the source and the observer are only coupled in the sense,
that the source must be sending some sort of notification and the target must be able to handle it.
someButton.onClick = handler; basically does exactly that, but it's just so elegant and concise you don't make a fuzz about it.
someButton.onClick(handler); probably is a little better, since you can have multiple handlers, although this is rarely required of UI components. But in the end, if you want signalers, go with signalers.
Now when it comes to AOP, it is not the right approach in this situation. It's not a clever hack to wire up components between one another, but about dealing with cross-cutting concerns, such as adding a log, a history or even things as a persistence layer across a multitude of modules.
In general, try not to modularize or split the little parts of your application.
It is ok to have some spaghetti in your codebase, as long as
the spaghetti segments are well encapsulated
the spaghetti segments are small enough to be understood or otherwise refactored/rewritten in a reasonable amount of time, without breaking the app (which point no. 1 should guarantee)
Try rather to split the whole application into autonomous parts, which interact through concise interfaces. If a part grows too big, refactor it just the same way.
edit:
In response to Tom's questions:
that's a matter of taste. in some frameworks people go as far as using external configuration files, but that makes little sense with haXe, since you need to instruct the compiler to force compilation of the dependencies you inject at runtime. Setting up the dependency in your code, in a central file, is just as much work and far simpler. For more structure, you can split the app into "modules", each module having a loader class responsible for registering the implementations it provides. In your main file, you load the modules.
That depends. I tend to declare them in the package of the class depending on them and later on refactor them to an extra package in case they prove to be needed elsewhere. By using anonymous types, you can also completely decouple things, but you'll have a slight performance hit on platforms as flash9.
I wouldn't abstract the button and then inject an implementation through IoC, but feel free to do so. I would explicitely create it, because in the end, it's just a button. It has a style, a caption, screen position and size and fires click events. I think, this is unnecessary modularization, as pointed out above.
Stick to SRP. If you do, no class will grow unneccessarily big. The role of the Main class is to initialize the app. When done, it should pass control to a login controller, and when that controller acquires a user object, it can pass it on to the main controller of the actual app and so forth. I suggest you read a bit about behavioral patterns to get some ideas.
greetz
back2dos
First of all, I'm not familiar with Haxe at all. However, I would answer that what is described here sounds remarkably similar to how I've learned to do things in .NET, so it sounds to me like this is good practice.
In .NET, you have an "Event" that fires when a user clicks a button to do something (like logon) and then a method executes to "handle" the event.
There will always be code that describes what method is executed in one class when an event in another class is fired. It is not unnecessarily complex, it is necessarily complex. In the Visual Studio IDE, much of this code is hidden in "designer" files, so I don't see it on a regular basis, but if your IDE doesn't have this functionality, you've got to write the code yourself.
As for how this works with your custom loader class, I hope someone here can provide you an answer.

Nerd Dinner validation rules question

In the NerdDinner tutorial, Step 5, mid way down under Complete Edit Action Method Implementations there is a paragraph:
The nice thing about our Edit implementation is that neither our Controller class nor our View template has to know anything about the specific validation or business rules being enforced by our Dinner model. We can add additional rules to our model in the future and do not have to make any code changes to our controller or view in order for them to be supported. This provides us with the flexibility to easily evolve our application requirements in the future with a minimum of code changes.
My question is what kind of rule might be added and in such a way that I don't lose my clean separation. I can see this code:
public static class ControllerHelpers {
public static void AddRuleViolations(this ModelStateDictionary modelState, IEnumerable<RuleViolation> errors) {
foreach (RuleViolation issue in errors) {
modelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
}
}
is better than this code:
catch {
foreach (var issue in dinner.GetRuleViolations()) {
ModelState.AddModelError(issue.PropertyName, issue.ErrorMessage);
}
return View(dinner);
}
because I do not have specific class/model information and can use it across the application. And, I can see how that is good if my error handling is simple like the above, but I do not see how I would add anything more complex for new business rules and was hoping for an example.
First understand that the code you posted really just "pulls" the errors from Model and places them on the View (via the ModelState). The flexibility comes in the fact that any new rules/edits will only need to touch the Model. i.e. you only have to hit the Dinner.cs code.
One thing I had to grok in the NerdDinner lessons was that validation will occur in both the Dinner.cs OnValidate() partial method and in the DinnersController.cs in the call to UpdateModel(). This call copies the text from the screen into the Model. If, for example, it tries to copy text to a float, it will update the ModelState and throw an error. The normal validation will not run.

Resources