Best place to load data when navigating XamarinForms Prism 6? - xamarin.forms

One of the cool features in Prism 6 is the deep linking and passing parameters. In a lot of cases, you'd want to use this parameter to look up data from a web service. Ideally this would be using async/await to get the data. Where is the best place to do this? The OnNavigatedTo method for example is a void.

Although I don't have a case for Deep Linking yet, I am doing many loads on many pages inside OnNavigatedTo and it is working great!
Here is a sample:
public void OnNavigatedTo(NavigationParameters parameters)
{
if (parameters != null &&
parameters.ContainsKey("MyKey"))
{
SomePrivateFieldInViewModel = (YourVariable)parameters["MyKey"];
//SomeWork
}
GetItems();
}
private async void GetItems()
{
try
{
SomeListInViewModel = await WebServices.GetEntity(SomePrivateFieldInViewModel);
//SomeWork
}
catch (Exception ex)
{
//SomeWork
}
}

Related

Blazor .Net server side where to load LocalStorage data

I use Blazor Preview 9 server side on .NET Core 3.0 and also the nuget package Blazored.LocalStorage for loading and saving data in Local Storage of the browser.
Now I want to load it ONCE time when required when loading the application.
For this I need to use OnFirstRenderer because it has to be on client side completely to access it's browser cache. Right now I use the page "/" (Index.razor) for it but I'm not pretty sure if this is the correct anchor or way for doing this:
[Parameter]
public string Test { get; set; }
protected async override Task OnAfterRenderAsync(bool firstRender)
{
try
{
if (firstRender)
{
await localStorage.SetItemAsync("TEST", "Hallo Welt");
}
if (Test == null)
{
Test = await localStorage.GetItemAsync<string>("TEST");
StateHasChanged();
}
}
catch (Exception ex)
{
throw;
}
}
Also I don't know how to make this available for all components:
is it best way to make a service with global variables and inject it into each component or doing it via CascadingValue method?
Thx!
OnAfterRender is now only called when the component is initialized and you can perform JS interop (it will be called every time the component is re-rendered after that - but firstRender will be false). So if you only want to load a value once from local storage you can do it during the firstRender as per the example below.
[Parameter]
public string Test { get; set; }
protected async override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
Test = await localStorage.GetItemAsync<string>("TEST");
}
}
In terms of making the value available to all components, you can either use a global state class or provide it via a cascading parameter. Either option will work and I don't really see one as better than the other, all I'd say is if you need other bits kept in state then use a state class, if you don't then probably go with a cascading parameter.
As per Mister Magoo's comment - it would be best to do this in the App.razor component so it would be loaded even in deep linking scenarios.

Spring MVC Validation - Avoiding POST-back

I'd like to validate a Spring 3 MVC form. When an element is invalid, I want to re-display the form with a validation message. This is pretty simple so far. The rub is, when the user hits refresh after an invalid submission, I don't want them to POST, I want them to GET. This means I need to do a redirect from the form POST (submission) to re-display the form with validation messages (the form is submitted via a POST).
I'm thinking the best way to do this is to use SessionAttributeStore.retrieveAttribute to test if the form is already in the user's session. If it is, use the store form, otherwise create a new form.
Does this sound right? Is there a better way to do this?
To solve this problem, I store the Errors object in the session after a redirect on a POST. Then, on a GET, I put it back in the model. There are some holes here, but it should work 99.999% of the time.
public class ErrorsRedirectInterceptor extends HandlerInterceptorAdapter {
private final static Logger log = Logger.getLogger(ErrorsRedirectInterceptor.class);
private final static String ERRORS_MAP_KEY = ErrorsRedirectInterceptor.class.getName()
+ "-errorsMapKey";
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView mav)
throws Exception
{
if (mav == null) { return; }
if (request.getMethod().equalsIgnoreCase(HttpMethod.POST.toString())) {
// POST
if (log.isDebugEnabled()) { log.debug("Processing POST request"); }
if (SpringUtils.isRedirect(mav)) {
Map<String, Errors> sessionErrorsMap = new HashMap<String, Errors>();
// If there are any Errors in the model, store them in the session
for (Map.Entry<String, Object> entry : mav.getModel().entrySet()) {
Object obj = entry.getValue();
if (obj instanceof Errors) {
if (log.isDebugEnabled()) { log.debug("Adding errors to session errors map"); }
Errors errors = (Errors) obj;
sessionErrorsMap.put(entry.getKey(), errors);
}
}
if (!sessionErrorsMap.isEmpty()) {
request.getSession().setAttribute(ERRORS_MAP_KEY, sessionErrorsMap);
}
}
} else if (request.getMethod().equalsIgnoreCase(HttpMethod.GET.toString())) {
// GET
if (log.isDebugEnabled()) { log.debug("Processing GET request"); }
Map<String, Errors> sessionErrorsMap =
(Map<String, Errors>) request.getSession().getAttribute(ERRORS_MAP_KEY);
if (sessionErrorsMap != null) {
if (log.isDebugEnabled()) { log.debug("Adding all session errors to model"); }
mav.addAllObjects(sessionErrorsMap);
request.getSession().removeAttribute(ERRORS_MAP_KEY);
}
}
}
}
It's not clear from your question but it sounds like your GET and POST actions are mapped to the same handler. In that case you can do something like:
if ("POST".equalsIgnoreCase(request.getMethod())) {
// validate form
model.addAttribute(form);
return "redirect:/me.html";
}
model.addAttribute(new MyForm());
return "/me.html";
In the JSP check if there are any error on the form and display as needed.
Such approach is called PRG (POST/REdirect/GET) design pattern I explained it few days ago as one of the answers:
Spring MVC Simple Redirect Controller Example
Hope it helps :)

How do i improve the legacy code implementation, Response.Redirect?

Some scenarios to ponder. There is a legacy code which has following implementation Example1 and Example2. If we try to implement MSDN recommendation then the legacy code fails.
Here is a Legacy code example:
Example 1:
void Page_Load() {
.... some code
if(condition) {
/// some condition
} else {
RedirectPage(url);
}
// another code block
// some other conditions.
}
Example 2:
a. File1.ascx
void Page_Load() {
try {
.. some code
base.CheckPreference();
RedirectPage(defaultPage);
}
catch(Exception ex) {
ExceptionHandling.GetErrorMessage(ex);
}
}
b. BaseClass.cs // this is the base class
void CheckPreference() {
try {
if(condition) {
RedirectPage(url1);
} else if(condition2) {
RedirectPage(url2);
} else {
// update session
}
}
catch(Exception ex) {
ExceptionHandling.GetErrorMessage(ex);
throw;
}
}
void RedirectPage(string url) {
Response.Redirect(url);
}
One possible way is to add a boolean field in the class e.g endExecution, set the field to true whenever RedirectPage is called.
We have to update RedirectPage code see code snippet below:
// Updated code - MSDN recommendation.
void RedirectPage(url) {
Response.Redirect(url, false);
this.Context.ApplicationInstance.CompleteRequest();
endExecution = true;
}
Please suggest some other better ways to improve the legacy code implementation.
Probably the most unintuitive thing for folks issuing a redirect is that in our minds we've already returned from the method what we call Respond.Redirect (or whatever the equivilent is in your language/platform of the day. All we've done is call a method.
Bottom line is that you have to stop processing the request to avoid trying to commit to responses for the same request. That would throw an exception on just about any platform I've worked with.
ASP.NET MVC improved this with the ActionResponse so that you are returning from the method (and terminating the remainder of request processing) with code that looks like this:
return Redirect(url);
Bottom line is that you need to get in the habit of returning from your event right after you perform your redirect. Any deviation from that habit needs to be documented in the code why. This will help make the application perform the way you expect.
The approach that you've taken is perfectly reasonable.

SEAM: Component "disinjected" "too soon" in interceptor?

Let's say I have the following interceptor in a SEAM app:
public class MyInterceptor {
#In
private Monitor myMonitor;
#AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
try {
myMonitor.a();
return ctx.proceed();
}
finally {
myMonitor.b();
}
}
}
myMonitor.a() works (so Monitor is correctly injected), myMonitor.b() fails because Monitor is already null. Seam Doc says: "Injected values are disinjected (i.e., set to null) immediately after method completion and outjection."
Is that what is happening? Can I do something to tell SEAM to "not yet" "disinject" the component? I can of course also do something like XContext.get(..), but I'm wondering whether this is a bug or a mistake from my side. thanks!
Try this one instead
Object response = null;
try {
myMonitor.a();
response = ctx.proceed();
} finally {
myMonitor.b();
}
return response;
regards,
Avoid using injection.
Try working around this problem. I see you have some sort of monitoring going on. Look at this interceptor that captures the amount of time a method is executed in Seam components. Try modifying your code to match that.
It works great!
Here is the link
Seam is working as advertised.
You could just ignore the disinjection:
public class MyInterceptor {
private Monitor myMonitor;
#In
private void setMonitor(Monitor aMonitor) {
if (aMonitor != null) {
myMonitor = aMonitor;
}
}
#AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
try {
myMonitor.a();
return ctx.proceed();
}
finally {
myMonitor.b();
myMonitor = null; //perform disinjection yourself
}
}
}
The caveat here is that Seam is disinjecting the reference for a reason. Seam wants to control the lifecycle and identity of "myMonitor" and by keeping a reference to it, you are not abiding by your contract with Seam. This could lead to unexpected behavior.
For instance, if myMonitor were for some reason in the Stateless scope, Seam might destroy it before ctx.proceed() returns, leaving you with a reference to a broken proxy. Best advice is to know the scope and lifecycle of what you are retaining since you are "living on the edge."

RhinoMocks Event Subscription

Being new to RhinoMocks and Unit Testing, I have come accross an issue that I cannot seem to find a resolution to (no matter how much documentation I read).
The issue is this: I have created an Interface that exposes 5 Events (to be used for a view in ASP.NET and the MVP Supervisory Controller pattern..... I know, I should be using MVC, but that's a whole other issue). Anyway, I want to test that when a certain event fires on the view, we'll call it "IsLoaded", that a method inside of my Presenter is called and, using Dependency Injection, a value is returned from the Dependency and set to the view. Here is where the problem starts: when I use Expect.Call(Dependency.GetInfo()).Return(SomeList), the Call never executes (without the mock.ReplayAll() method being invoked). Well, when I invoke the ReplayAll method, I get ExpectationExceptions because of the Subscription by the Presenter object to the other Events exposed by the View Interface.
So, for me to test that IView.IsLoaded has fired, I want to verify that IView.ListOfSomething has been updated to match the list I passed in via the Expect.Call(). However, when I set the expectation, the other Event subscriptions (which occur straight out of the constructor for the Presenter) fail the #0 Expectations of the test. What I get is, view.Save += this.SaveNewList tosses up a RhinoMocks ExpectationViolationException.
My million dollar question is this: Is it necessary I set expectations for ALL of my events (via [Setup]), or is there something that I'm missing/not understanding about how Unit Testing or RhinoMocks works?
Please bear in mind I am extremely new to Unit Testing, and therefore RhinoMocks. If it appears I don't know what I'm talking about, please feel free to point that out.
I'm working on a project where we used MVP and rhino mocks as well. What we did was simply expect all event subscriptions in every test.
private void SetupDefaultExpectations()
{
_mockView.Initializing += null; LastCall.IgnoreArguments();
_mockView.SavingChanges += null; LastCall.IgnoreArguments();
}
Then we built a extension method on IMockedObject (from RhinoMocks) to trigger events in the unit tests and un-wrap exceptions so that they can be expected in the standard NUnit way.
static class IMockedObjectExtension
{
public static void RaiseEvent(this IMockedObject mockView, string eventName, EventArgs args)
{
EventRaiser eventraiser = new EventRaiser(mockView, eventName);
try
{
eventraiser.Raise(mockView, args);
}
catch (TargetInvocationException ex)
{
throw ex.InnerException;
}
}
public static void RaiseEvent(this IMockedObject mockView, string eventName)
{
RaiseEvent(mockView, eventName, EventArgs.Empty);
}
}
This could then be used from the unit test like this
using(_mocks.Record())
{
Expect.Call(dependency.GetInfo()).Return(someList);
}
using(_mocks.Playback())
{
Presenter presenter = new Presenter(_mockView, dependency);
(_mockView as IMockedObject).RaiseEvent("SavingChanges");
}
To eliminate duplication between presenter tests we have refactored this to a BasePresenterTest base class which sets up this basic structure for all presenter tests and exposes helper methods to the sub class.
public abstract class BasePresenterTest<VIEW> where VIEW : IBaseView
{
protected MockRepository _mocks;
protected VIEW View { get; private set; }
protected abstract void SetUp();
protected abstract void TearDown();
protected abstract void SetupDefaultExpectations();
[SetUp]
public virtual void BaseSetUp()
{
_mocks = new MockRepository();
View = _mocks.CreateMock<VIEW>();
SetUp();
}
[TearDown]
public virtual void BaseTearDown()
{
TearDown();
View = null;
_mocks = null;
}
protected virtual void BaseSetupDefaultExpectations()
{
//Setup default expectations that are general for all views
SetupDefaultExpectations();
}
protected virtual IDisposable Record()
{
IDisposable mocksRecordState = _mocks.Record();
BaseSetupDefaultExpectations();
return mocksRecordState;
}
protected virtual IDisposable Playback()
{
return _mocks.Playback();
}
protected void RaiseEventOnView(string eventName)
{
(View as IMockedObject).RaiseEvent(eventName);
}
}
This eliminates alot of code from the tests in our project.
We still use a old version of RhinoMocks but I will try to update this once we move to a later version.

Resources