0

I try to use content query in web application but it throw an exception " Lucene.Net.Store.AlreadyClosedException: this IndexReader is closed". Please give help me resolve that problem.

var startSettings = new RepositoryStartSettings
        {
            Console = Console.Out,
            StartLuceneManager = true, // <-- this is necessary
            IsWebContext = false,
            PluginsPath = AppDomain.CurrentDomain.BaseDirectory,
        };

        using (Repository.Start(startSettings))
        {
            var resultQuery = ContentQuery.Query("+InTree:@0 + DisplayName:*@1*", null, folderPath, q);

        }
dinhienhy
  • 15
  • 6
  • We could not reproduce the issue, can you please tell us the SN version you're using? Or can you share the whole app somehow? – Miklós Tóth Nov 30 '16 at 21:05
  • As a side-question: do you really need a heavy tool that has its own index? Because if you can, you could use the Sense/Net Client library that connects to a portal through the REST API, that is the recommended way to write an SN tool. It is still c# code that you write, it is just simpler to maintain a tool like that. – Miklós Tóth Nov 30 '16 at 21:07
  • I'm using SN version 6.5.3. I have already used Sense/Net client through REST API, but I could not use that method to implement the search feature. So I need use ContentQuery to search content in a Tree. – dinhienhy Dec 01 '16 at 03:08
  • There is a Content.QueryAsync method in the client api that executes the same query and gives you a list of content. It is possible that it was addded later than you checked :) (http://github.com/sensenet/sn-client-dotnet) What do you plan to do with the results? – Miklós Tóth Dec 01 '16 at 07:38
  • Thanks for your support. Client Api is the best solution. Can you give the way to check a ClientContext is Initialized? How to remove current ClientContext to Initialize a new object – dinhienhy Dec 01 '16 at 10:37
  • Can you give an example for this? Why do you want to re-initialize the client? Currently this is not possible, it throws an exception, we thought this use case does not exist: ) If you want to connect to multiple Sense/Net repositories at the same time, you can initialize the client with multiple servers and provide them explicitely to Load oor create methods. – Miklós Tóth Dec 01 '16 at 13:56
  • My example: web application connects to SN repository. And users sync with SN user. when user login in web application, a ClientContext is initialized. But when a new session user start, i think we need create a new ClinetContext. – dinhienhy Dec 01 '16 at 14:47
  • With which user credentials do you want to connect to SN from your web app? Is there a single admin account that you want to use, or do you want to send requests to SN using the currently logged in user? In the first case you can initialize a client in app start once. If it is the second case, than a workaround may be to still initialize a client in the app start, but when you make a call (e.g. a query) using the client, you could create a ServerContext object on-the-fly (with the current user name and password) and provide that to the method. – Miklós Tóth Dec 01 '16 at 15:07
  • Of course the approach depends on the use case: if you need to perform an administrative task, then you should use an admin account. If you need to query with permissions applied (e.g. get a list of documents accessible by the currently logged in user), then you'll have to provide the current user credentials. The point is, it is enough to construct a ServerContext object on-the-fly. The point of the Initialize is only to provide a predefined ServerContext(s), because in most cases there is only a single one. Your case is a bit different, but nothing is wrong with that :). – Miklós Tóth Dec 01 '16 at 15:10
  • that's right. I need to query with permissions applied. Could you show me how to construct a ServerContext object on-the-fly? – dinhienhy Dec 01 '16 at 15:40
  • The same way you do it when initializing the client: new ServerContext() and fill the url, username and password properties. – Miklós Tóth Dec 01 '16 at 15:54
  • And simply provide this object to any of the client api methods, like the Content.QueryAsync method. – Miklós Tóth Dec 01 '16 at 15:56
  • Thank Miklós Tóth so much! – dinhienhy Dec 01 '16 at 16:08
  • Let me know if we can help with anything else :) And if you think the answer below is ok and contains enough details, please mark it as the correct one, so that others know. – Miklós Tóth Dec 03 '16 at 19:36

1 Answers1

0

The recommended way to connect to Sense/Net from a different application (app domain) is through the REST API. It is much easier to maintain and involves less configuration (the only exception is where you are working inside the Sense/Net application itself, or you only have a single application and you do not want to access Sense/Net from anywhere else, and you are willing to deal with a local index of Sense/Net and all the config values it needs, etc).

Connecting through the REST API does not mean you have to send HTTP requests manually (although that is also not complicated at all): there is a .Net client library which does that for you. You can access all content metadata or binaries through the client, you can upload files, query content, manage permissions, etc.

// loading a content
dynamic content = await Content.LoadAsync(id);
DateTime date = content.BirthDate;

// querying
var results = await Content.QueryAsync(queryText);

To use it in a web application, you have to do the following:

  • initialize the client context once, at the beginning of the application life cycle (e.g. app start)
  • if you need to make requests to Sense/Net in the name of the currently logged in user (e.g. because you want to query for documents accessible by her), than you have to create a new ServerContext object for every user with the username/password of that user, and provide this object to any client call (e.g. load or save content methods).
var sc = new ServerContext 
{ 
    Url = "http://example.com", 
    Username = "user1", 
    Password = "asdf" 
};

var content = await Content.LoadAsync(id, sc);
Miklós Tóth
  • 1,490
  • 13
  • 19