SearchManager

Aug 28, 2012 at 4:43 AM

I'm working on an app and we want to implement search. I've found the SearchManager in Okra but I can't work out how to use it. Is there any sample around with which I can see how to use it?

Aug 28, 2012 at 6:33 AM

With a bit of digging I think we've managed to work out what we needed to do with the SearchManager.

The following assumes you're using Okra.MEF

  • Create an AppBootstrapper implementation
  • Using your instance of the AppBootstrapper set the SearchManager.SearchPageName
  • Create your view/ viewModel and implement ISearchPage (on the ViewModel is probably ideal)
  • Add the [PageExport]/ [ViewModelExport] attributes
  • Enjoy magic

The biggest pain point we've got now is that we've got an authentication token that's passed around to each page (using navigation arguments) but since Search doesn't actually get fired using the NavigationManager (well, you don't fire it) it's impossible to pass arguments that way. Our work around has been to implement INavigationAware and in the NavigatingFrom method set an application setting that we read in the search page activation (and then clear out).

Would be curious if anyone has any better ideas on how to do that.

Coordinator
Aug 28, 2012 at 11:54 AM

slace,

Sorry there's not much (well, none!) documentation or samples for the search functionallity. This was added in a recent release of the Okra App Framework and I haven't found the time to write about it yet.

Anyhow, it looks like you have got the steps required yourself. You didn't mention where in the AppBootstrapper you are setting the SearchManager.SearchPageName but I would suggest this is done in an overriden AppBootstrapper.SetupServices() method.

Regarding passing the authentication token between pages, is this the same value across the application? Since you are using the Okra.MEF infrastructure then you should be able to get MEF to inject any shared state when it is composing each page. For example,

[Export]
[Shared]
public class TokenStore
{
    public AuthenticationToken
    {
        get {...}
    }
}

[ViewModelExport("Search")]
public class SearchViewModel : ISearchPage
{
    [Import]
    public TokenStore TokenStore {get; set;}

    ...
}

You can centralise the token creation/storage in the TokenStore, and then reuse it in any of the view-models or other services in the application. Does this sound like it would work in your situation?

As an aside, since the search functionallity is fairly new I'd be very interested in any feedback you have on it - bugs, new features, etc. I've got some ideas of my own but it's alway good to hear what the community thinks.

Regards,

    Andy

Aug 28, 2012 at 11:04 PM

I like the idea of using MEF to inject the token the only problem I can see with that is that we are authenticating with a web service. Since the user credentials are requested when the app first launches (we're not storing creds) so the token is created on-the-fly. I'd like to *then* shove it into MEF but I'm not sure that that is possible.

One thing that I can think would be nice is when the NavigationFrom is called to go to a search page the NavigationMode is Search.

Coordinator
Aug 29, 2012 at 12:02 PM

One thing to remember is that the user may see the search page without ever seeing the app home page - for example navigate to the search charm, enter some search text, then select an unopen application - the design guidelines say that the app should start and navigate directly to the search page (which is the behaviour that the Okra App Framework should give you by default). Of course you could detect in the search page that there is no auth token and overlay a log-in UI, but don't assume that if a user gets to the search page that they must have seen the home page first (note that Okra will currentlycreate the home page & view model then navigate to the search page, but this may change in future as an optimisation).

Anyway, back to the question - as far as I am aware the 'Windows Store apps' version of MEF does not include recomposition so as you say there is no way to change an existing import once it has been composed. However this doesn't stop you from having the TokenStore.AuthenticationToken property having a setter. Since it is marked as "Shared" then this is a singleton class so your login UI could import the TokenStore, perform authentication, then set the AuthenticationToken property when it is available. The search view-model would import the same TokenStore so could then retrieve the value.

What I often do in my apps is to separate the login logic completely into a separate class which exposes a property of type Task<AuthenticationToken>. In my view-models I import this service, await the task, and once an authentication token is returned can continue execution as required. For the first request of the auth token you can automatically display the log-in UI (which means that it doesn't matter if your user has activated via the home page or via search or ...). For all subsequent requests the cached auth token is returned syncronously.

Regarding having a NavigationMode.Search value I'll look into it.

Andy

Aug 30, 2012 at 6:10 AM

Yeah to be able to "MEF-ise" our auth we'd need to restructure quite a bit inside the application, and since the app is to be delivered in the next week it might just have to go into v2 :P.

Coordinator
Aug 30, 2012 at 9:59 AM

If you are looking for a quick-fix then you could just have a class with the auth token in a static property with a getter and setter - when you first get the token then set the property, continue to pass it around via the navigation arguments if you wish, and for the search page just read the property. One warning is to be very careful with situations where your search page is shown and the auth token is still null.

Good luck with the app submission and it would be great to hear when you hit the store...

Andy

Aug 30, 2012 at 10:44 PM

Yeah that's what we've been going with, having a singleton that is around that may or may not contain the security token and if there isn't one it's back to the login screen you go!