跳过 Html.ActionLink 的只读字段的生成
Skip generation of readonly fields for Html.ActionLink
我有一个基本请求对象 RequestBase
定义如下:
public abstract class RequestBase
{
public abstract string Area { get; }
public abstract string ActionName { get; }
public abstract string LinkName { get; }
public abstract string ControllerName { get; }
}
和这样的子类:
public class RequestTest : RequestBase
{
public Guid Id { get; set; }
public RequestTest()
{
Id = Guid.Empty;
}
#region implementation of RequestBase
public override string Area
{
get { return "MyArea"; }
}
public override string ActionName
{
get { return "Overview"; }
}
public override string ControllerName
{
get { return "Test"; }
}
public override string LinkName
{
get { return "Click me for awesome"; }
}
#endregion
}
问题。我想写一个帮助程序以这种方式建立链接:
@Html.ActionLinkByRequest(new RequestTest{Id = Guid.Empty})
我目前已经实现了
public static MvcHtmlString ActionLinkByRequest(this HtmlHelper helper, RequestBase request, object htmlAttributes = null)
{
return helper.ActionLink(request.LinkName, request.ActionName, request.ControllerName, request, htmlAttributes);
}
不幸的是它呈现为:
<a href="/MyArea/Test/Overview?EventId=00000000-0000-0000-0000-000000000000&ActionName=Overview&LinkName=Click%20me%20for%20awesome&ControllerName=Test">Click me for awesome</a>
但我只想
<a href="/MyArea/Test/Overview?EventId=00000000-0000-0000-0000-000000000000">Click me for awesome</a>
没有只读字段。因为它们是只读的,所以我不需要在查询字符串中显式地使用它们,因为我的 Action
等待具体实现 RequestTest
并且无论如何都会有它们:
public ActionResult Overview(RequestTest request)
{
// do things here
return View();
}
有什么想法可以跳过操作链接的只读字段的生成吗?也许通过某种方式使用反射?
通过评论编辑
这行得通吗?
public static MvcHtmlString ActionLinkByRequest(this HtmlHelper helper, RequestBase request, object htmlAttributes = null)
{
var rvd = new RouteValueDictionary();
foreach(var prop in request.GetType().GetProperties().Where(p => p.CanRead && p.CanWrite))
{
// add the property by name and the value
// rvd.Add(prop.Name, prop.GetValue());
}
// add the area (check if not already existing)
if(!rvd.ContainsKey("Area"))
rvd.Add("Area", request.AreaName);
return helper.ActionLink(request.LinkName, request.ActionName, request.ControllerName, request, htmlAttributes);
}
public static MvcHtmlString ActionLinkByRequest(this HtmlHelper helper, RequestBase request, object htmlAttributes = null)
{
var rvd = new RouteValueDictionary(request);
rvd.Remove("ActionName");
rvd.Remove("ControllerName");
rvd.Remove("LinkName");
return helper.ActionLink(request.LinkName, request.ActionName, request.ControllerName, rvd, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
在 Robert 的评论之后,我想出了以下对我有用的方法:
public static MvcHtmlString ActionLinkByRequest(this HtmlHelper helper, RequestBase request, object htmlAttributes = null)
{
// create new value-dictionary to be passed
var rvd = new RouteValueDictionary();
// loop through properties of the request
foreach (var prop in request.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.CanRead && p.CanWrite))
{
// add name/value to route-dictionary
rvd.Add(prop.Name, prop.GetValue(request));
}
// check if area is needed
if (!rvd.ContainsKey("Area"))
{
rvd.Add("Area", request.Area);
}
return helper.ActionLink(request.LinkText, request.ActionName, request.ControllerName, rvd, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
我有一个基本请求对象 RequestBase
定义如下:
public abstract class RequestBase
{
public abstract string Area { get; }
public abstract string ActionName { get; }
public abstract string LinkName { get; }
public abstract string ControllerName { get; }
}
和这样的子类:
public class RequestTest : RequestBase
{
public Guid Id { get; set; }
public RequestTest()
{
Id = Guid.Empty;
}
#region implementation of RequestBase
public override string Area
{
get { return "MyArea"; }
}
public override string ActionName
{
get { return "Overview"; }
}
public override string ControllerName
{
get { return "Test"; }
}
public override string LinkName
{
get { return "Click me for awesome"; }
}
#endregion
}
问题。我想写一个帮助程序以这种方式建立链接:
@Html.ActionLinkByRequest(new RequestTest{Id = Guid.Empty})
我目前已经实现了
public static MvcHtmlString ActionLinkByRequest(this HtmlHelper helper, RequestBase request, object htmlAttributes = null)
{
return helper.ActionLink(request.LinkName, request.ActionName, request.ControllerName, request, htmlAttributes);
}
不幸的是它呈现为:
<a href="/MyArea/Test/Overview?EventId=00000000-0000-0000-0000-000000000000&ActionName=Overview&LinkName=Click%20me%20for%20awesome&ControllerName=Test">Click me for awesome</a>
但我只想
<a href="/MyArea/Test/Overview?EventId=00000000-0000-0000-0000-000000000000">Click me for awesome</a>
没有只读字段。因为它们是只读的,所以我不需要在查询字符串中显式地使用它们,因为我的 Action
等待具体实现 RequestTest
并且无论如何都会有它们:
public ActionResult Overview(RequestTest request)
{
// do things here
return View();
}
有什么想法可以跳过操作链接的只读字段的生成吗?也许通过某种方式使用反射?
通过评论编辑
这行得通吗?
public static MvcHtmlString ActionLinkByRequest(this HtmlHelper helper, RequestBase request, object htmlAttributes = null)
{
var rvd = new RouteValueDictionary();
foreach(var prop in request.GetType().GetProperties().Where(p => p.CanRead && p.CanWrite))
{
// add the property by name and the value
// rvd.Add(prop.Name, prop.GetValue());
}
// add the area (check if not already existing)
if(!rvd.ContainsKey("Area"))
rvd.Add("Area", request.AreaName);
return helper.ActionLink(request.LinkName, request.ActionName, request.ControllerName, request, htmlAttributes);
}
public static MvcHtmlString ActionLinkByRequest(this HtmlHelper helper, RequestBase request, object htmlAttributes = null)
{
var rvd = new RouteValueDictionary(request);
rvd.Remove("ActionName");
rvd.Remove("ControllerName");
rvd.Remove("LinkName");
return helper.ActionLink(request.LinkName, request.ActionName, request.ControllerName, rvd, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}
在 Robert 的评论之后,我想出了以下对我有用的方法:
public static MvcHtmlString ActionLinkByRequest(this HtmlHelper helper, RequestBase request, object htmlAttributes = null)
{
// create new value-dictionary to be passed
var rvd = new RouteValueDictionary();
// loop through properties of the request
foreach (var prop in request.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.CanRead && p.CanWrite))
{
// add name/value to route-dictionary
rvd.Add(prop.Name, prop.GetValue(request));
}
// check if area is needed
if (!rvd.ContainsKey("Area"))
{
rvd.Add("Area", request.Area);
}
return helper.ActionLink(request.LinkText, request.ActionName, request.ControllerName, rvd, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
}