SolrNet: SolrConnectionException (400) bad request when attempting to Add and Commit - c#

I have gotten to the point where SolrNet executes the "Add" method but when I try to "Commit" is when I receive the error. The following is my schema.xml, model, code calling it, and the error I get. Even stranger is that despite the error, the model is added to my Solr index AFTER I restart Tomcat (so it still adds my model despite the error but not immediately):
schema.xml (fields and fieldtypes):
<!-- Fields -->
<field name="part_numbers" type="my_string_exact" indexed="true" stored="true" multiValued="true" />
<field name="page_url" type="my_string_exact" indexed="true" stored="true" />
<field name="product_name" type="my_string" indexed="true" stored="true" />
<!-- FieldTypes -->
<fieldType name="my_string_exact" class="solr.StrField" sortMissingLast="true" omitNorms="true"/>
<fieldType name="my_string" class="solr.TextField" sortMissingLast="true" omitNorms="true">
<analyzer type="index">
<tokenizer class="solr.KeywordTokenizerFactory" />
<filter class="solr.LowerCaseFilterFactory" />
</analyzer>
<analyzer type="query">
<tokenizer class="solr.KeywordTokenizerFactory" />
<filter class="solr.LowerCaseFilterFactory" />
</analyzer>
</fieldType>
<fieldType name="my_int" class="solr.IntField" omitNorms="true" />
Model (Product.cs) *NOTE - PageId uses the Solr default "id" that is a string, unique and required:
public class Product
{
[SolrUniqueKey("id")]
public string PageId { get; set; }
[SolrField("part_numbers")]
public ICollection<string> PartNumbers { get; set; }
[SolrField("page_url")]
public string PageUrl { get; set; }
[SolrField("product_name")]
public string Name { get; set; }
}
Code initializing, calling the Add and Commit *NOTE - This is a unit test so init is only called once:
Startup.Init<Product>("http://localhost:8080/solr");
Product testProd = new Product() {
EPiPageId = "44",
Name = "TestProd3",
PageUrl = "/TestProd3",
PartNumbers = new List<string>() { "000022222", "000000333333" }
};
var solr = ServiceLocator.Current.GetInstance<ISolrOperations<Product>>();
solr.Add(testProd);
solr.Commit(); // Bad Request Error occurs here.
Error Msg:
SolrNet.Exceptions.SolrConnectionException was unhandled by user code
HResult=-2146232832
Message=The remote server returned an error: (400) Bad Request.
Source=SolrNet
StackTrace:
at SolrNet.Impl.SolrConnection.Post(String relativeUrl, String s) in c:\prg\SolrNet\svn\SolrNet\Impl\SolrConnection.cs:line 104
at SolrNet.Commands.CommitCommand.Execute(ISolrConnection connection) in c:\prg\SolrNet\svn\SolrNet\Commands\CommitCommand.cs:line 71
at SolrNet.Impl.SolrBasicServer`1.Send(ISolrCommand cmd) in c:\prg\SolrNet\svn\SolrNet\Impl\SolrBasicServer.cs:line 87
at SolrNet.Impl.SolrBasicServer`1.SendAndParseHeader(ISolrCommand cmd) in c:\prg\SolrNet\svn\SolrNet\Impl\SolrBasicServer.cs:line 91
at SolrNet.Impl.SolrBasicServer`1.Commit(CommitOptions options) in c:\prg\SolrNet\svn\SolrNet\Impl\SolrBasicServer.cs:line 54
at SolrNet.Impl.SolrServer`1.Commit() in c:\prg\SolrNet\svn\SolrNet\Impl\SolrServer.cs:line 24
InnerException: System.Net.WebException
HResult=-2146233079
Message=The remote server returned an error: (400) Bad Request.
Source=System
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at HttpWebAdapters.Adapters.HttpWebRequestAdapter.GetResponse() in c:\prg\SolrNet\svn\HttpWebAdapters\Impl\HttpWebRequestAdapter.cs:line 36
at SolrNet.Impl.SolrConnection.GetResponse(IHttpWebRequest request) in c:\prg\SolrNet\svn\SolrNet\Impl\SolrConnection.cs:line 160
at SolrNet.Impl.SolrConnection.Post(String relativeUrl, String s) in c:\prg\SolrNet\svn\SolrNet\Impl\SolrConnection.cs:line 101
InnerException:
EDIT Thanks to Paige for the answer: The issue was a "waitFlush" error that is a bug with older versions of SolrNet. The version of SolrNet that I was using was from VS NuGet that was 0.3.1 (which I assumed was their latest stable build). Their google code site does not have their most recent build but the build server (here: http://teamcity.codebetter.com/project.html?projectId=project36&guest=1 under "artifacts") did have the latest with the fix to this bug. Problem solved for me.

I am guessing that you are probably seeing a waitFlush error in your Tomcat Logs and you are using version 4.X of Solr. If that is the case, this is a known issue with Solr 4.x and older versions of SolrNet. To fix this issue, upgrade to a later release of the SolrNet library. You can download it from the Build Server. Click on Artifacts to get a link to the zip.

Related

"Object reference not set to an instance of an object" retrieving multiple records with IOrganizationService

I am creating a plugin for Dynamics 365 in C#. I am trying to make request using fetchXML, however I am getting the following error: Object reference not set to an instance of an object.
Here is my code:
public void Execute(IServiceProvider serviceProvider)
{
// Obtain the tracing service
ITracingService tracingService =
(ITracingService)serviceProvider.GetService(typeof(ITracingService));
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)
serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationService svc = (IOrganizationService)serviceProvider.GetService(typeof(IOrganizationService));
try
{
var id = context.InputParameters["leadid"] as string;
var fetchXml = $#"<?xml version=""1.0"" encoding=""utf-16""?>
<fetch>
<entity name=""lead"">
<attribute name=""leadid"" />
<link-entity name=""new_sitecorevisit"" from=""new_new_parent_leadid"" to=""leadid"">
<attribute name=""new_visitduration"" />
<filter>
<condition attribute=""new_new_parent_leadid"" operator=""eq"" value=""{id}"" />
</filter>
</link-entity>
</entity>
</fetch>";
EntityCollection result = svc.RetrieveMultiple(new FetchExpression(fetchXml));
context.OutputParameters["data"] = result;
}
catch (Exception ex)
{
tracingService.Trace("Error: {0}", ex.ToString());
throw;
}
}
I believe that it is being thrown when this line is reached:
EntityCollection result = svc.RetrieveMultiple(new FetchExpression(fetchXml)); as removing this fixes the issue. However, I do not know why it is throwing this error. I have checked to see if it is an error with the fetchXml variable or the id variable, however these are passing as expected.
I have tested retrieving the data using JavaScript and the data is returned as expected, however, this is not useful for creating a .NET plugin.
Is there a mistake that I am making?

XML deserialisation fails with nested classes (inner classes)

Edit
I have a problem at deserialising an XML file, containing inner classes (or nested classes).
I have following class diagram:
[XmlRoot(ElementName = "HM")]
public class OwnClass : BaseClass{
...
public OwnClass(){} // default constructor
...
}
I have the following _xmlMessageFormatter declaration (based on System.Messaging):
this._xmlMessageFormatter = new System.Messaging.XmlMessageFormatter();
System.Type[] OwnTypes = new System.Type[30];
OwnTypes[0] = typeof(Baseclasses.OwnClass); /* TR */
...
this._xmlMessageFormatter.TargetTypes = OwnTypes;
Edit: this is what the XML looks like:
<?xml version="1.0"?>
<HM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>124</ID>
<TC>TR</TC>
</HM>
All of this is working fine.
Now I add a new class inside the definition of OwnClass:
[XmlRoot(ElementName = "HM")]
public class OwnClass : BaseClass {
[XmlElement(ElementName = "INS")]
public ClassInside f_Inside;
...
public OwnClass(){} // default constructor
...
public class ClassInside{
...
public class ClassInside(){}
...} // end of ClassInside
} // end of OwnClass
I've also added the corresponding targettype:
OwnTypes [27] = typeof(BaseClasses.OwnClass.ClassInside); // the number of the array is correct.
Edit: the XML file looks now as follows:
<?xml version="1.0"?>
<HM xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ID>125</ID>
<TC>TR</TC>
<TR>
<ID>1</ID>
<CD>MOVE</CD>
</TR>
</HM>
The _xmlMessageFormatter cannot handle the deserialisation, as you can see here:
Source code:
Object temp;
temp = this._xmlMessageFormatter.Read(message);
For getting more information, I've typed ? temp = this._xmlMessageFormatter.Read(message); in the immediate window (I'm working with Visual Studio), this is what I get:
'temp = this._xmlMessageFormatter.Read(message)' threw an exception of type 'System.InvalidOperationException'
Data: {System.Collections.ListDictionaryInternal}
HResult: -2146233079
HelpLink: null
InnerException: {"There was an error reflecting field 'f_Inside'."}
Message: "There was an error reflecting type 'BaseClasses.AnotherClass'."
Source: "System.Xml"
StackTrace: " at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)\r\n at
System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)\r\n at
System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)\r\n at
System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)\r\n at
System.Messaging.XmlMessageFormatter.CreateTargetSerializerTable()\r\n at
System.Messaging.XmlMessageFormatter.Read(Message message)"
TargetSite: {System.Xml.Serialization.TypeMapping ImportTypeMapping(System.Xml.Serialization.TypeModel,
System.String,
ImportContext,
System.String,
System.Xml.Serialization.XmlAttributes,
Boolean,
Boolean,
System.Xml.Serialization.RecursionLimiter)}
I have two issues with the error message:
It mentions f_Inside. This looks correct, but I have used f_Inside as a general fieldname for all my classes, and the reason I mention this:
It mentions AnotherClass while I have send a message of the form OwnClass.
=> I'm having serious doubts about the correctness of the error message. Is there anybody who knows what I can do now (or how the _xmlFormatter works?)
Edit: added background
All of this is part of a messaging service: one application is sending a message, the other one is receiving it (using the System.Messaging.MessageQueue objects). The serialisation/deserialisation is just a part of it.
Thanks in advance
The problem is solved and it had nothing to do with deserialisation of nested classes:
In one of my classes (AgainAnotherClass), I had following source code:
[XmlElement(ElementName = "SA")]
[XmlElement(ElementName = "SA")]
public string SomeAttribute { get; set; }
(a typical case of Copy/Paste)
The fact that I had two lines with XmlElement caused the problem.
The exception looked as follows:
InnerException: {"There was an error reflecting field 'f_Inside'."}
Message: "There was an error reflecting type '<NameSpace>.AgainOtherClass'."
The InnerException made me believe that there was a problem with the nested class, while the Message spoke about a completely other class. I decided to follow the InnerException.
That was wrong! So, in case of C# exceptions where InnerException and Message contradict each other, first check the Message, then (maybe) the InnerException.

The Id cannot be computed, since the navigation source 'values' cannot be resolved to a known entity set from model

I am accessing my OData service with following metadata (simplified and obfuscated to the relevant part), this is generated by using Microsoft.AspNet.OData :
<Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
<DataServices>
<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="MyProject.Api.Models">
<EntityType Name="ValuesContainer">
<Key>
<PropertyRef Name="id" />
</Key>
<Property Name="id" Type="Edm.Guid" Nullable="false" />
<NavigationProperty Name="values" Type="Collection(MyProject.Api.Models.Value)"/>
</EntityType>
<EntityType Name="Value">
<Key>
<PropertyRef Name="id"/>
</Key>
<Property Name="value" Type="Edm.String" />
<Property Name="id" Type="Edm.Guid" Nullable="false" />
<Property Name="valuesContainerId" Type="Edm.Guid"/>
<NavigationProperty Name="valuesContainer" Type="MyProject.Api.Models.ValuesContainer">
<ReferentialConstraint Property="valuesContainerId" ReferencedProperty="id"/>
</NavigationProperty>
</EntityType>
</Schema>
</DataServices>
</Edmx>
Some example the output it generates:
{
"#odata.context": "https://localhost:5002/v1/odata/$metadata#ValuesContainer(values())",
"value": [
{
"id": "2996e6ea-3e72-4b4c-8b3b-b076e34f6dac",
"values": [
{
"value": "Hello world",
"valuesContainerId": "2996e6ea-3e72-4b4c-8b3b-b076e34f6dac",
"id": "3d10fcfa-27a2-4c21-7e01-08d783bf6c40"
}
]
}
]
}
When I try to get a ValuesContainer via using the Simple.Odata.Client I receive the following error:
Microsoft.OData.ODataException: 'The Id cannot be computed, since the navigation source 'values' cannot be resolved to a known entity set from model.'
Part where the exception is thrown:
namespace Simple.OData.Client.V4.Adapter
{
public class ResponseReader : ResponseReaderBase
...
private ODataEntryAnnotations CreateAnnotations(ODataResource odataEntry)
{
string id = null;
Uri readLink = null;
Uri editLink = null;
if (_session.Adapter.GetMetadata().IsTypeWithId(odataEntry.TypeName))
{
try
{
// Over here my exception occurs, calculating the odataEntry.Id.AbsoluteUri
id = odataEntry.Id.AbsoluteUri;
readLink = odataEntry.ReadLink;
editLink = odataEntry.EditLink;
}
catch (ODataException)
{
/// Yep, the library contains this typo
// Ingored
}
}
return new ODataEntryAnnotations
{
Id = id,
TypeName = odataEntry.TypeName,
ReadLink = readLink,
EditLink = editLink,
ETag = odataEntry.ETag,
MediaResource = CreateAnnotations(odataEntry.MediaResource),
InstanceAnnotations = odataEntry.InstanceAnnotations,
};
}
...
}
Is my metadata wrong and/or is there a workaround for this? It's not really required to solve it, but having that many exceptions thrown during runtime causes too much overhead as these are expensive operations.
Found the solution, had to add the Contained attribute to my Value.
I was getting this error, I resolved it by setting:
MergeOption = MergeOption.NoTracking;
on my Client, as I was only doing read-only operations at the time.
Found that answer here: https://github.com/OData/odata.net/issues/2211
I was plagued by this particular error as well. But setting Contained attribute wasn't an option for us. Posting this in case anyone else ever runs into this.
The problem for me was that the IModelConfiguration declaration for my entity's key was silently failing (due to another config setting that was trying to set up an Action incorrectly).
So based on the error from Echamus' original post:
The Id cannot be computed, since the navigation source 'values' cannot be resolved to a known entity set from model
The solution that fixed it for me was making sure the key was defined for the entity type that "values" contains (in this case, ValueModelConfiguration):
using Microsoft.AspNet.OData.Builder;
using Microsoft.AspNetCore.Mvc;
using MyProject.Api.Models;
namespace MyProject.Api.Configuration.Model_Configurations
{
public class ValueModelConfiguration : IModelConfiguration
{
public void Apply(ODataModelBuilder builder, ApiVersion apiVersion)
{
builder.EntitySet<Value>(nameof(Value)).EntityType.HasKey(v => v.id);
// other configurations for your entity (e.g. value) may be here
}
}
}
(Note: Value above is whatever entity for the "navigation source" being complained about in the original error)
If you already have this defined, but you have other configurations occurring before/after it, those other configurations may be the problem and may be causing this particular line to fail silently.
Hope that helps save someone some time in the future.

Showing PDF-File with MVVM Cross on Android and IOS

I want to open a PDF on the Phone via the File-Path but i cant figure out how i could do this properly without using 3rd party packages.
You have any suggestion for this?
I already tried to use this on Android:
public void OpenFile(string filePath)
{
var fileToOpen = new Java.IO.File(filePath);
var uri = FileProvider.GetUriForFile(Application.Context, Application.Context.PackageName + ".fileprovider", fileToOpen);
var intent = new Intent();
var mime = IOUtil.GetMimeType(uri.ToString());
intent.SetAction(Intent.ActionView);
intent.SetDataAndType(uri, mime);
intent.SetFlags(ActivityFlags.NewTask);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
Application.Context.StartActivity(intent);
}
But i get the following Error:
Unhandled Exception:
Java.Lang.NullPointerException: Attempt to invoke virtual method
'android.content.res.XmlResourceParser
android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager,
java.lang.String)' on a null object reference
first you should addd this code to your manifest file :
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.easyphotopicker.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/filepaths"
tools:replace="android:resource"/>
</provider>
and create filepaths :
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path="" /> //root directory of the device new File("/");
<files-path name="files" path="" /> //context.getFilesDir()
<cache-path name="cache" path="" /> //context.getCacheDir()
<external-path name="external" path="" /> //Environment.getExternalStorageDirectory()
<external-files-path name="name" path="path" /> //context.getExternalFilesDirs()
<external-cache-path name="name" path="path" /> //getExternalCacheDirs()
</paths>
Your error is telling us that there is no file at the location matching that's passed into the function. There's a few ways of doing this, one of them is as shown. After accepting permissions to access folders and files, this should be one of the simplest ways. You seem to be close:
public void OpenPdfFile(string filename)
{
var f = new Java.IO.File(filename);
if (f.Exists())
{
System.Diagnostics.Debug.WriteLine("File exists!");
try
{
var openFileIntent = new Intent(Intent.ActionView);
openFileIntent.SetDataAndType(Android.Net.Uri.FromFile(f), "application/pdf");
openFileIntent.SetFlags(ActivityFlags.NoHistory);
StartActivity(Intent.CreateChooser(openFileIntent, "Open pdf file"));
}
catch (ActivityNotFoundException)
{
//handle when no available apps
}
}
}
I haven't tested your work, but the first thing would be to see if you added this to the Manifest file
android:authorities="com.{package}.{name}.fileprovider"
since your code says Application.Context.PackageName + ".fileprovider"

'System.InvalidOperationException' when LINQ to SQL using WCF on WP8

This is the code where the exception occurs:
public Listado()
{
InitializeComponent();
ListadoWebService();
}
public void ListadoWebService()
{
// InitializeComponent();
ServiceTours.ServiceToursClient cl = new ServiceTours.ServiceToursClient();
cl.ListadoCompleted += new EventHandler<ListadoCompletedEventArgs>(Listado2);
cl.ListadoAsync();
}
private void Listado2(object sender, ListadoCompletedEventArgs e)
{
listB.ItemsSource = e.Result; // listB is ListBox in WP8
}
I get following Exception:
An exception of type 'System.InvalidOperationException' occurred in System.ServiceModel.ni.dll but was not handled in user code
I would like to say that I directly followed this tutorial on MSDN
So the final Service Reference url is: http://IP/WcfTours/ServiceTours.svc as it should be. //99.99.99 represents IP
World Wide Web Services (HTTP) in Allow an app through Windows Firewall is allowed for domain public and private.
Virtual Directory is created.
Will somebody please help me with setting the endpoint please ?
Exception message:
{System.InvalidOperationException: An endpoint configuration section for contract 'ServiceTours.IServiceTours' could not be loaded because more than one endpoint configuration for that contract was found. Please indicate the preferred endpoint configuration section by name.
at System.ServiceModel.Description.ConfigLoader.LookupChannel(String configurationName, String contractName, Boolean wildcard)
at System.ServiceModel.Description.ConfigLoader.LoadChannelBehaviors(ServiceEndpoint serviceEndpoint, String configurationName)
at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName)
at System.ServiceModel.ChannelFactory.InitializeEndpoint(String configurationName, EndpointAddress address)
at System.ServiceModel.ChannelFactory1..ctor(String endpointConfigurationName, EndpointAddress remoteAddress)
at System.ServiceModel.EndpointTrait1.CreateSimplexFactory()
at System.ServiceModel.ClientBase1.CreateChannelFactoryRef(EndpointTrait1 endpointTrait)
at System.ServiceModel.ClientBase1.InitializeChannelFactoryRef()
at System.ServiceModel.ClientBase1..ctor()
at PhoneApp1.ServiceTours.ServiceToursClient..ctor()
at PhoneApp1.Listado.ListadoWebService()
at PhoneApp1.Listado..ctor()}
As soon as you add a Web Service reference in your project a new ServiceReferences.ClientConfig file is created in the root folder of your project. Open it somewhere and look for:
<client>
<endpoint .... name="endpointName" />
<endpoint .... name="endpointName2" />
</client>
In your case you have more than one records there. so select the appropriate and pass the name into contructor of ServiceToursClient.
new ServiceToursClient("endpointName")

Categories

Resources