Ошибка десериализации ASP.NET MongoDB

Я пытаюсь удалить все документы в моей коллекции MongoDB через REST api, встроенный в ASP.NET MVC 4, и я столкнулся с ошибкой при вводе localhost: 50491 / api / document:

Ошибка при десериализации свойства Id класса Acord_Rest_API.Models.Document: невозможно десериализовать строку из BsonType ObjectId.

Мой контроллер выглядит так:

public class DocumentController : ApiController
{
    public readonly MongoConnectionHelper<Document> docs;

    public DocumentController()
    {
        docs = new MongoConnectionHelper<Document>();
    }

    public IList<Document> getAllDocs()
    {
        var alldocs = docs.collection.FindAll();
        return alldocs.ToList();
    }
}

Мой документ MongoDB выглядит так? введите описание изображения здесь

Что мне здесь не хватает?

Мой класс, который подключается к БД:

public class MongoConnectionHelper<T> where T: class
{
    public MongoCollection<T> collection { get; private set; }

    public MongoConnectionHelper()
    {
        string connectionString = "mongodb://127.0.0.1";
        var server = MongoServer.Create(connectionString);
        if (server.State == MongoServerState.Disconnected)
        {
            server.Connect();
        }
        var conn = server.GetDatabase("Acord");
        collection = conn.GetCollection<T>("Mappings");
    }
}

ИЗМЕНИТЬ вот мое решение: введите описание изображения здесь

MongoConnectionHelper выполняет соединение с БД, DocumentController имеет методы для извлечения всех документов, а Document содержит то, что вы предложили в своем ответе.

ИЗМЕНИТЬ вот класс документа:

[DataContract]
public class Document
{
    public ObjectId _id { get; set; }

    [DataMember]
    public string MongoId
    {
        get { return _id.ToString(); }
        set { _id = ObjectId.Parse(value); }
    }
    public IList<string> alldocs { get; set; }
}

person Mike Barnes    schedule 11.01.2013    source источник


Ответы (3)


Mongo Id не является «строкой», и библиотека Mongo.Bson не будет автоматически сериализовать его в строку. Если вы используете библиотеку Mongo.Bson, вам необходимо установить для свойства id вашего класса тип ObjectId, доступный в этой библиотеке.

Проблема здесь в том, что сериализатор .net не знает, как сериализовать ObjectId пользовательского типа, который является монго, встроенным в Id (не знаю почему). Он не помечен как [Serializable], поэтому вам нужно заставить ASP.NET обойти его или создать другой класс, у которого его нет, и преобразовать его в строку.

Если вам нужна строка для использования в вашем приложении, вы должны отключить сериализацию MongoId в xml (если это то, что вы пытаетесь сделать), затем вы можете добавить такое свойство в свой класс:

[XmlIgnore]
public ObjectId _id { get; set; }

public string MongoId
{
    get { return _id.ToString(); }
    set { _id = ObjectId.Parse(value); }
}

Альтернативой является создание отдельного сопоставленного класса для управления возвращаемыми данными.

РЕДАКТИРОВАТЬ В этом случае вы должны использовать подход «согласия». Это включает в себя украшение вашего класса, чтобы он выглядел следующим образом:

[DataContract]
public class Document
{
    public ObjectId _id { get; set; }

    [DataMember]
    public string MongoId
    {
        get { return _id.ToString(); }
        set { _id = ObjectId.Parse(value); }
    }

...

DataMember пометит только эти свойства для сериализации. Вы используете классы POCO для своего объекта «Документ»? Если да, то все должно работать нормально.

Однако я бы рекомендовал создать отображенное представление объекта «Документ» для публичной передачи. В этих ситуациях вы почти всегда в конечном итоге захотите немного другой "контракт" с вашей реальной сущностью базы данных.

person Gats    schedule 11.01.2013
comment
Я отредактировал вопрос и добавил свое подключение. Я хотел бы вернуть результат FindAll в Json. - person Mike Barnes; 11.01.2013
comment
Как вы посоветуете мне создать отображение документа? с интерфейсом? или это глупый вопрос? - person Mike Barnes; 11.01.2013
comment
Вовсе нет, есть множество способов сделать это, и трудно дать совет, не видя структуру вашего решения в VS. Папка контрактов с классами, которым вы сопоставляете, всегда хороша. Контракт - это собственный класс, и вы можете сопоставить его с помощью linq ... Выберите (x = ›new DocumentContract () {MongoId = ObjectId.ToString (), A = xA, B = xB ... и т. Д. Или такой инструмент, как Automapper если у вас много разных классов. - person Gats; 11.01.2013
comment
Спасибо, человек, я отредактировал вопрос и добавил снимок решения. - person Mike Barnes; 11.01.2013
comment
Теперь мне кажется, что элемент «ClaimSynchronizationProcess» не соответствует ни одному полю или свойству класса Acord_Rest_API.Models.Document error? Есть ли у вас какие-либо предложения? - person Mike Barnes; 11.01.2013
comment
Можете ли вы показать мне, где вы сопоставляете свою сущность с той, что находится в коллекции Mongo? - person Gats; 11.01.2013
comment
Как вы заполняете свой документ-контракт? Вы используете EF? - person Gats; 12.01.2013
comment
Я не уверен, что буду с тобой полностью честен? Я новичок в Restful Web API и ASP.NET? как мне это проверить? вы были очень полезны до сих пор !!! - person Mike Barnes; 13.01.2013
comment
Судя по всему, проблема не в успокаивающей части, а в части доступа к данным. - person Gats; 14.01.2013
comment
Допустим, я хотел вернуть только список всех документов из этого, нужно ли мне что-то вроде public IList<BsonDocument> allDocs {get; set;};? потому что я думаю, что мой класс документа неправильный › - person Mike Barnes; 14.01.2013

Более простой подход - указать MongoDB обрабатывать строковое поле как ObjectId. Это легко сделать с помощью атрибута BsonType.

[BsonRepresentation(BsonType.ObjectId)]
public string _id { get; set; }
person Ofir    schedule 19.01.2016
comment
Вы только что сэкономили мне много времени. Спасибо - person monstertjie_za; 22.08.2017

Я думаю, что вам не хватает соглашения [BsonId], поэтому ваш класс должен выглядеть так:

[DataContract]
public class Document
{
    [BsonId]
    public ObjectId _id { get; set; }

    [DataMember]
    public string MongoId
    {
        get { return _id.ToString(); }
        set { _id = ObjectId.Parse(value); }
    }
person Abdelhalim FELLAGUE CHEBRA    schedule 09.08.2016