MongoDB: MVC не сериализует BsonId при публикации

Я не могу получить ObjectId для модели, чтобы вернуться со значением, используя официальную библиотеку MongoDB csharp. Когда я отправляю форму, которая отправляется обратно в контроллер, PageID всегда возвращается {0000000000000000000000000} в модели. Отображаемый HTML-код имеет действительный идентификатор, это одно поле никогда не возвращается должным образом из сообщения формы.

HTML-рендеринг: <input id="PageID" name="PageID" type="hidden" value="4f83b5ccd79f660b881887a3" />

Это то, что у меня есть.

Модель:

public class PageModel
    {
        public PageModel()
        {
            CanEdit = false;
            CancelRequest = false;
        }

        [BsonId]
        public ObjectId PageID { get; set; }

        [Display(Name = "Page URL")]
        public string PageURL { get; set; }

        [AllowHtml]
        [Display(Name = "Content")]
        public string Value { get; set; }

        [Display(Name = "Last Modified")]
        public DateTime LastModified { get; set; }

        [BsonIgnore]
        public bool CancelRequest { get; set; }
        [BsonIgnore]
        public bool CanEdit { get; set; }

    }

Пост контролера:

[HttpPost]
        public ActionResult Edit(PageModel model)
        {
            // check to see if the user canceled
            if (model.CancelRequest)
            {
                return Redirect(model.PageURL);
            }

            // check for a script tag to prevent
            if (!model.Value.Contains("<script"))
            {
                // save to the database
                model.LastModified = DateTime.Now;
                collection.Save(model);

                // return to the page
                return Redirect(model.PageURL);
            }
            else
            {
                ModelState.AddModelError("Value", "Disclosures discovered a script in the html you submitted, please remove the script before saving.");
            }

            return View(model);
        }

Вид:

@model LeulyHome.Models.PageModel

@{
    ViewBag.Title = "";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@using (Html.BeginForm())
{ 
    <fieldset>
        <legend>Edit Page</legend>
        <div class="control-group">
            @Html.LabelFor(m => m.PageURL, new { @class = "control-label" })
            <div class="controls">
                @Html.TextBoxFor(m => m.PageURL, new { @class = "input-xlarge leu-required span9" })
                @Html.ValidationMessageFor(m => m.PageURL, null, new { @class = "help-block" })
            </div>
        </div>
        <div class="control-group">
            @Html.LabelFor(m => m.Value, new { @class = "control-label" })
            <div class="controls">
                @Html.TextAreaFor(m => m.Value)
                @Html.ValidationMessageFor(m => m.Value, null, new { @class = "help-block" })
            </div>
        </div>
        <div class="control-group">
            @Html.LabelFor(m => m.LastModified, new { @class = "control-label" })
            <div class="controls">
                @Html.DisplayFor(m => m.LastModified)
                @Html.HiddenFor(m => m.LastModified)
            </div>
        </div>

        @Html.HiddenFor(m => m.PageID)
        @Html.HiddenFor(m => m.CancelRequest)

        <div class="form-actions">
            <button type="submit" class="btn btn-primary">Save Page</button>
            <button type="button" class="btn btn-danger" id="cancelBtn">Cancel Changes</button>
        </div>
    </fieldset>
}

@section Footer {
    <script type="text/javascript" src="@Url.Content("~/Content/ckeditor/ckeditor.js")"></script>
    <script language="javascript" type="text/javascript">
        $(document).ready(function () {
            // adjust the editor's toolbar
            CKEDITOR.replace('Value', {
                toolbar: [["Bold", "Italic", "Underline", "-", "NumberedList", "BulletedList", "-", "Link", "Unlink"],
                  ["JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock"],
                  ["Cut", "Copy", "Paste", "PasteText", "PasteFromWord", "-", "Print", "SpellChecker", "Scayt"], ["Source", "About"]]
            });

            $("#cancelBtn").click(function () {
                $("#CancelRequest").val("True");
                $("#updateBtn").click();
            });
        });
    </script>
}

person uadrive    schedule 11.04.2012    source источник


Ответы (3)


Похоже, вы отправляете строковое значение для PageID, которое вы ожидаете от объекта типа ObjectId.

Привязка модели не будет знать, как взять эту строку и превратить ее в ObjectId. Если вы посмотрите на класс ObjectId в MongoDriver, вы увидите, что он довольно громоздкий.

Мы довольно часто используем mongodb, а для наших идентификаторов мы просто используем строки, которые обеспечивают большую гибкость. Я не уверен, в каком случае вам нужен класс ObjectId в качестве идентификатора вашего документа, но он может вам не понадобиться.

Отсюда кажется, что у вас есть два варианта.

  1. Измените идентификатор вашего документа на строки или что-то еще
  2. Напишите пользовательский модуль связывания модели для класса ObjectId.

Надеюсь, это поможет :)

person Brett Allred    schedule 11.04.2012
comment
Спасибо за информацию. Я опытен в MVC, но новичок в MongoDB. Ваш второй вариант на самом деле дал мне достаточно информации, чтобы продолжить, и я смог создать подшивку модели, чтобы позаботиться об этом за меня. Вот пример одного из них. Джо-Стивенс .com/2011/06/12/ - person uadrive; 11.04.2012

Создать привязку:

открытый класс ObjectIdBinder: IModelBinder {

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
    return !string.IsNullOrWhiteSpace(result.AttemptedValue) ? ObjectId.Parse(result.AttemptedValue) : ObjectId.Empty;
}

}

Создайте ModelBinderConfig:

пространство имен Nasa8x.CMS { открытый класс ModelBinderConfig { public static void Register (ModelBinderDictionary binder) { binder.Add (typeof (ObjectId), new ObjectIdBinder());

        binder.Add(typeof(string[]), new StringArrayBinder());

        binder.Add(typeof(int[]), new IntArrayBinder());

    }
}

}

Зарегистрируйтесь на Global.cs:

 protected void Application_Start()
            {  

                ModelBinderConfig.Register(ModelBinders.Binders);

                WebApiConfig.Register(GlobalConfiguration.Configuration);
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);    

            }
person nasavietnam    schedule 09.09.2013

Если вам не нужно, чтобы свойство PageID в вашем классе С# имело тип ObjectId, но вы хотите воспользоваться этим типом на стороне MongoDB, вы можете позволить драйверу позаботиться о преобразовании в вашем классе-определении:

public class PageModel
{

    [BsonId]
    [BsonRepresentation(BsonType.ObjectId)]
    public string PageID { get; set; }

}
person zlit    schedule 11.05.2016