MVC 3 Telerik Grid не возвращает временную метку для просмотра модели

Обновление: я еще ничего не понял. Кажется, что это должно работать так, как есть.

У меня есть сетка телерика, которую я привязал к модели просмотра. Сетка в основном отображает имя и тип объекта Vehicle. В Datakeys я добавил поля VehicleID и Timestamp. Когда сетка публикуется для обновления ajax, поле Timestamp имеет значение null.

Я проверил, что поле Timestamp в модели представления имеет значение, когда оно передается в представление.

Вот соответствующий код:

Просмотр:

...
@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
    columns.Bound(o => o.VehicleID).Visible(false);        
    columns.Bound(o => o.VehicleName);
    columns.Bound(o => o.VehicleType);
})
.DataBinding(dataBinding =>
    {
        dataBinding.Server().Select("Index", "Vehicle");
        dataBinding.Ajax().Select("_Index", "Vehicle").Enabled(true);
        dataBinding.Ajax().Update("_SaveVehicle", "Vehicle");
        dataBinding.Ajax().Delete("_DeleteVehicle", "Vehicle");
    })
    .Scrollable(scrolling => scrolling.Enabled(true))
    .Sortable(sorting => sorting.Enabled(true))
    .Pageable(paging => 
        paging.Enabled(true)
        .PageSize(20)
        .Position(GridPagerPosition.Bottom))
    .Filterable(filtering => filtering.Enabled(true))
    .Groupable(grouping => grouping.Enabled(true))
    .Footer(true)
    .ToolBar(toolbar => toolbar.Template(
        @<text>
            @using (Html.BeginForm("ExportCsv", "Vehicle", FormMethod.Post, new {id = "export"}))
            {
                <text>
                    <input type="submit" value="Export to CSV" id="export" />
                </text>
            }

            <label class="error">@ViewBag.AjaxErrorMessage</label>

        </text>
        ))            

    .Columns(columns =>
        {
            columns.Command(command =>
                {
                    command.Custom("details").Text("Details").Action("Edit", "Vehicle").HtmlAttributes(new { style = "text-align: center" }) ;
                    command.Edit().ButtonType(GridButtonType.Image);
                    command.Delete().ButtonType(GridButtonType.Image);
                }).Width(165);
        })
    .DataKeys(dataKeys => 
        {
            dataKeys.Add(key => key.Timestamp).RouteKey("Timestamp");
            dataKeys.Add(key => key.VehicleID).RouteKey("VehicleID"); 

        })
    .ClientEvents(events => events.OnEdit("onEdit"))
    .ColumnContextMenu()
    .Resizable(config =>
        {
            config.Columns(true);
        })
    .Reorderable(config =>
        {
            config.Columns(true);
        })

)

<script type = "text/javascript">
function onEdit(e) {
    $(e.form).find('#VehicleType').data('tDropDownList').select(function (dataItem) {
        return dataItem.Text == e.dataItem['vehicleType'];
    });
}
</script>

Модель просмотра:

using System;
using System.ComponentModel.DataAnnotations;

namespace ShopLog.ViewModels
{
    public class VehicleIndexViewModel
    {

    //public IEnumerable<Vehicle> Vehicles { get; set; }
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid VehicleID { get; set; }

    [Timestamp]
    public Byte[] Timestamp { get; set; }

    [Required]
    [Display(Name = "Vehicle Name")]
    [MaxLength(30, ErrorMessage = "The {0} must be no more than {2} characters long.")]
    public string VehicleName { get; set; }

    [Display(Name = "Fuel Type")]
    [StringLength(30, ErrorMessage = "\"{0}\" must be no more than {1} characters long.")]
    public string FuelType { get; set; }

    [Display(Name = "Notes")]
    [DataType(DataType.MultilineText)]
    public string Notes { get; set; }

    [UIHint("VehicleType")]
    [Display(Name = "Type")]
    public string VehicleType { get; set; }

    [Display(Name = "Transmission Type")]
    public String TransmissionType { get; set; }
    }
}

Посткод контроллера для обновления Помещение точки останова в первой строке показывает, что свойство timestamp в VehicleIndexViewModel имеет значение null. Я попытался получить временную метку из коллекции форм, но и там она пуста.

[AcceptVerbs(HttpVerbs.Post)]
    [GridAction]
    public ActionResult _SaveVehicle(VehicleIndexViewModel vehicleIndexViewModel, FormCollection formcollection)
    {          

        if (TryUpdateModel(vehicle))
        {
            try
            {
                //Delete the record
                db.Entry(vehicle).State = EntityState.Modified;
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                ViewBag.AjaxErrorMessage = "That record has been edited by someone else since you started editing it.";
            }
            catch (DataException)
            {
                ViewBag.AjaxErrorMessage = "Error saving data, please try again.";
            }
        }
        //Rebind the grid
        PopulateVehicleTypes();
        return View(new GridModel(GetIndexViewData()));
    }

Спасибо!


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


Ответы (1)


Вот что я понял:

byte[] не возвращается обратно из ViewModel. Почему? Я не знаю.

В итоге я сделал поле «Временная метка» в моей ViewModel строкой вместо байта []. Когда я передаю данные из модели в модель представления, я вызываю «Convert.ToBase64String(value)». Когда я передаю данные из ViewModel обратно в модель, вызовите «Convert.FromBase64String(value)».

Модель:

[Timestamp]
public Byte[] Timestamp { get; set; }

ViewModel:

[Timestamp]
public string Timestamp {get; set;}

Контроллер:

    [AcceptVerbs(HttpVerbs.Post)]
    [GridAction]
    public ActionResult _SaveVehicle(VehicleIndexViewModel vehicleIndexViewModel)
    {
        Vehicle vehicle = Mapper.Map<VehicleIndexViewModel, Vehicle>(vehicleIndexViewModel);

        if (TryUpdateModel(vehicle))
        {
            try
            {
                //Delete the record
                db.Entry(vehicle).State = EntityState.Modified;
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException)
            {
                ViewBag.AjaxErrorMessage = "That record has been edited by someone else since you started editing it.";
            }
            catch (DataException)
            {
                ViewBag.AjaxErrorMessage = "Error saving data, please try again.";
            }
        }
        //Rebind the grid
        PopulateVehicleTypes();
        return View(new GridModel(GetIndexViewData()));
    }

Сопоставления Automapper в Global.ascx

AutoMapper.Mapper.CreateMap<ShopLog.Models.Vehicle, ShopLog.ViewModels.VehicleIndexViewModel>().ForMember(m => m.Timestamp, opt => opt.ResolveUsing<VehicleTimestampResolver>());
AutoMapper.Mapper.CreateMap<ShopLog.ViewModels.VehicleIndexViewModel, ShopLog.Models.Vehicle>().ForMember(m => m.Timestamp, opt => opt.ResolveUsing<VehicleIndexViewModelTimestampResolver>());

    public class VehicleTimestampResolver : AutoMapper.ValueResolver<Vehicle, string>
    {
        protected override string ResolveCore(Vehicle source)
        {
            return Convert.ToBase64String(source.Timestamp);
        }
    }

    public class VehicleIndexViewModelTimestampResolver : AutoMapper.ValueResolver<ShopLog.ViewModels.VehicleIndexViewModel, byte[]>
    {
        protected override byte[] ResolveCore(ShopLog.ViewModels.VehicleIndexViewModel source)
        {
            return Convert.FromBase64String(source.Timestamp);
        }
    }

Вид: (обратите внимание на ключи данных)

@(Html.Telerik().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
    columns.Bound(o => o.VehicleID).Visible(false);        
    columns.Bound(o => o.VehicleName);
    columns.Bound(o => o.VehicleType);
})    
.DataBinding(dataBinding =>
    {
        dataBinding.Server().Select("Index", "Vehicle");
        dataBinding.Ajax().Select("_Index", "Vehicle").Enabled(true);
        dataBinding.Ajax().Update("_SaveVehicle", "Vehicle");
        dataBinding.Ajax().Delete("_DeleteVehicle", "Vehicle");
    })
    .Scrollable(scrolling => scrolling.Enabled(true))
    .Sortable(sorting => sorting 
        .Enabled(true)
        .OrderBy(sortOrder => sortOrder.Add(o => o.VehicleName).Ascending())
        .SortMode(GridSortMode.MultipleColumn))
    .Pageable(paging => 
        paging.Enabled(true)
        .PageSize(20)
        .Position(GridPagerPosition.Bottom))
    .Filterable(filtering => filtering.Enabled(true))
    .Groupable(grouping => grouping.Enabled(true))
    .Footer(true)
    .ToolBar(commands => commands
        .Custom()
            .HtmlAttributes(new {id = "export"})
            .Text("Export to CSV")
                .Action("ExportCsv", "Vehicle", new { page = 1, orderBy = "~", filter = "~" }))                                                     
    .Columns(columns =>
        {
            columns.Command(command =>
                {
                    command.Custom("details").Text("Details").Action("Edit", "Vehicle").HtmlAttributes(new { style = "text-align: center" }) ;
                    command.Edit().ButtonType(GridButtonType.Image);
                    command.Delete().ButtonType(GridButtonType.Image);
                }).Width(165);
        })
    .DataKeys(dataKeys => 
        {
            dataKeys.Add(key => key.Timestamp).RouteKey("Timestamp");
            dataKeys.Add(key => key.VehicleID).RouteKey("VehicleID"); 

        })
    .ClientEvents(events => events 
        .OnEdit("onEdit")
        .OnDataBound("onDataBound"))
    .ColumnContextMenu()
    .Resizable(config =>
        {
            config.Columns(true);
        })
    .Reorderable(config =>
        {
            config.Columns(true);
        })        
)

Единственное, что осталось от этого, — это выяснить, где отображать «ViewBag.AjaxErrorMessage», когда он возвращается в представление, но это не должно быть слишком сложно. :)

person user1304444    schedule 12.04.2012