Asp.Net MVC 5 - 如何在Html.ActionLink通过一个复杂的对象作为路径值(),所以默认模式粘结剂可以映射呢? [英] Asp.Net mvc 5 - How can I pass a complex object as route value in Html.ActionLink() so default model binder can map it?

查看:183
本文介绍了Asp.Net MVC 5 - 如何在Html.ActionLink通过一个复杂的对象作为路径值(),所以默认模式粘结剂可以映射呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含搜索,排序和寻呼参数,以及要被编辑的记录的ID的对象

我想这个对象传递到Html.ActionLink()作为路径值对象,因此所得到的查询字​​符串将被默认的模型绑定到编辑动作的参数,这是一个EditViewModel被正确映射。

的想法是,在编辑操作完成后,它可以回到重定向到索引和保持相同的寻呼/排序位置,在相同的数据集,并且通过相同的搜索字符串过滤

编辑视图模型:

 公共类EditViewModel
{
    公共SearchSortPageViewModel SearchSortPageParams {搞定;组; }
    公众诠释标识{搞定;组; }    公共EditViewModel()
    {
        SearchSortPageParams =新SearchSortPageViewModel();
        ID = 0;
    }    公共EditViewModel(SearchSortPageViewModel searchSortPageParams,INT ID)
    {
        SearchSortPageParams = searchSortPageParams;
        ID = ID;
    }
}公共类SearchSortPageViewModel
{
    公共字符串SearchString在{搞定;组; }
    公共字符串SortCol {搞定;组; }
    公共字符串SortOrder的{搞定;组; }
    公众诠释页{搞定;组; }
    公众诠释每页{搞定;组; }
}

Edit操作:

 公众的ActionResult编辑(EditViewModel EVM)
    {
        / * ... * /
    }

当我做到这一点的看法:

  @model MyApp.Areas.Books.ViewModels.Books.IndexViewModel
...
@ {EditViewModel EVM =新EditViewModel(Model.SearchSortPageParams,item.ID);}
@ Html.ActionLink(编辑,编辑,EVM)

我得到这样的:

<$p$p><$c$c>http://localhost:63816/Books/Books/Edit/4?SearchSortPageParams=MyApp.Areas.Base.ViewModels.SearchSortPageViewModel

不过,我想这样的:

<$p$p><$c$c>http://localhost:63816/Books/Books/Edit/4?SearchSortPageParams.SearchString=abc&SearchSortPageParams.SortCol=name&SearchSortPageParams.SortOrder=asc&SearchSortPageParams.Page=1&SearchSortPageParams.PageSize=3

我已经能够通过迄今已有对象的唯一方法手动prepare查询字符串,如:

  @ {字符串theQueryString = + @ + evm.SearchSortPageParams.SearchString与&amp; SearchSortPageParams.SortCol =SearchSortPageParams.SearchString =+ @ + evm.SearchSortPageParams.SortCol&放大器; SearchSortPageParams.SortOrder =+ @ evm.SearchSortPageParams.SortOrder +与&amp; SearchSortPageParams.Page =+ @ evm.SearchSortPageParams.Page +与&amp; SearchSortPageParams.PageSize =+ @ evm.SearchSortPageParams.PageSize;}
&LT; A HREF =@ Url.Action(编辑,新的{} evm.Id)@(theQueryString)&gt;编辑&LT; / A&GT;

我想编写自定义模型绑定的,但似乎傻如果给出格式化为它期望的方式查询字符串,默认的模型绑定已处理嵌套对象。

我也想过写一个自定义对象序列化,输出其默认模型联编需要一个串行格式,但还没有钻进这个路线。

最后,我想不上不下的EditViewModel因此没有嵌套的,才有了断然列出的所有属性。但是,它的效果并不理想。

那么,什么是最好的方式去?


解决方案

据我所知,你不能直接传递复杂的对象,但你可以避免通过传递<$ C打造自己的查询字符串$ C> RouteValueDictionary :

  @ Html.ActionLink(编辑,编辑,新RouteValueDictionary {
    {SearchSortPageParams.SortOrder,evm.SearchSortPageParams.SortOrder},
    {/ *等.. * /}
})

根据您的需要呢?这应该生成查询字符串。

其他唯一的替代办法是使用反射来遍历模型的属性,并生成该字典的方式,但将在我看来,是过度设计。

当然,我一般会在这种情况下,你只需要你的操作方法建议采取单独的参数:

 公众的ActionResult搜索(字符串搜索字符串,SortOrder的中将sortOrder,...)

我想一般认为这是通过GET参数的方法的更合适的方式(当然,这有可能会笨拙,如果你有很多的参数)。然后,你可以做到以下几点,这是非常整洁:

  @ Html.ActionLink(编辑,编辑,
    新{中将sortOrder = evm.SearchSortPageParams.SortOrder,...})

I have an object containing searching, sorting and paging parameters as well as an id of a record to be edited.

I'd like to pass this object into Html.ActionLink() as a route value object, so that the resulting query string will be correctly mapped by the default model binder into the Edit action's parameter, which is an EditViewModel.

The idea is that after the Edit action completes, it can redirect back to the Index and maintain the same paging/sorting position, in the same data set, and filtered by the same search string.

Edit View Model:

public class EditViewModel
{
    public SearchSortPageViewModel SearchSortPageParams { get; set; }
    public int Id { get; set; }

    public EditViewModel() 
    {
        SearchSortPageParams = new SearchSortPageViewModel();
        Id = 0;
    }

    public EditViewModel(SearchSortPageViewModel searchSortPageParams, int id)
    {
        SearchSortPageParams = searchSortPageParams;
        Id = id;
    }
}

public class SearchSortPageViewModel
{
    public string SearchString { get; set; }
    public string SortCol { get; set; }
    public string SortOrder { get; set; }
    public int Page { get; set; }
    public int PageSize { get; set; }
}

Edit action:

public ActionResult Edit(EditViewModel evm)
    {
        /* ... */
    }

When I do this in the view:

@model MyApp.Areas.Books.ViewModels.Books.IndexViewModel
...
@{EditViewModel evm = new EditViewModel(Model.SearchSortPageParams, item.ID);}
@Html.ActionLink("Edit", "Edit", evm)

I get this:

http://localhost:63816/Books/Books/Edit/4?SearchSortPageParams=MyApp.Areas.Base.ViewModels.SearchSortPageViewModel

But I want this:

http://localhost:63816/Books/Books/Edit/4?SearchSortPageParams.SearchString=abc&SearchSortPageParams.SortCol=name&SearchSortPageParams.SortOrder=asc&SearchSortPageParams.Page=1&SearchSortPageParams.PageSize=3

The only way I have been able to pass the object so far has been to manually prepare the query string, like this:

@{string theQueryString = "?SearchSortPageParams.SearchString=" + @evm.SearchSortPageParams.SearchString + "&SearchSortPageParams.SortCol=" + @evm.SearchSortPageParams.SortCol + "&SearchSortPageParams.SortOrder=" + @evm.SearchSortPageParams.SortOrder + "&SearchSortPageParams.Page=" + @evm.SearchSortPageParams.Page + "&SearchSortPageParams.PageSize=" + @evm.SearchSortPageParams.PageSize;}
<a href="@Url.Action("Edit", new { evm.Id })@(theQueryString)">Edit</a>

I thought of writing a custom model binder, but it seems silly given that the default model binder already handles nested objects if formatted as a query string in the way it expects.

I also thought of writing a custom object serializer which outputs a serial format which the default model binder expects, but haven't yet gone down that route.

Finally, I thought of flattening out the EditViewModel so there is nothing nested, just have all the properties listed out flatly. But, it's not ideal.

So, what is the best way to go?

解决方案

As far as I know, you can't pass the complex object directly, but you can avoid having to build the query string yourself by passing a RouteValueDictionary:

@Html.ActionLink("Edit", "Edit", new RouteValueDictionary {
    {"SearchSortPageParams.SortOrder", evm.SearchSortPageParams.SortOrder },
    { /* etc... */ }
})

This should generate the query string as you need it.

The only other alternative would be use reflection to iterate over the properties of the model and generate this dictionary that way but that would, in my opinion, be over-engineered.

Of course, I would generally suggest in this situation that you just have your action method take separate parameters:

public ActionResult Search(string searchString, SortOrder sortOrder, ...)

I'd generally consider this to be a more appropriate way to pass GET parameters to a method (of course, this could get unwieldy if you have a lot of parameters). Then you can just do the following, which is much tidier:

@Html.ActionLink("Edit", "Edit",
    new { sortOrder = evm.SearchSortPageParams.SortOrder, ... })

这篇关于Asp.Net MVC 5 - 如何在Html.ActionLink通过一个复杂的对象作为路径值(),所以默认模式粘结剂可以映射呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆