Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 跳过Html.ActionLink的只读字段的生成_C#_.net_Asp.net Mvc_Reflection_Extension Methods - Fatal编程技术网

C# 跳过Html.ActionLink的只读字段的生成

C# 跳过Html.ActionLink的只读字段的生成,c#,.net,asp.net-mvc,reflection,extension-methods,C#,.net,Asp.net Mvc,Reflection,Extension Methods,我有一个基本请求对象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; } }

我有一个基本请求对象
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>
有没有办法跳过actionlink的只读字段的生成?也许通过某种方式使用反射

按评论编辑

这样行吗

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);
}

在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));
}

为什么要将整个请求对象作为助手中的第四个参数传递?应该传递什么?只有需要传递的值,我猜这更像是
new{Id=request.Id}
,但我不知道每个实现所需的值可以有自己的值。或者我可以创建一个新的
RouteValueDictionary
,只包含具体请求实现的属性,并通过“手动”添加区域吗?这样您就可以扩展RequestBase以包含更多属性。我懂了。我看不出您在哪里将任何属性定义为只读,所以我看不出如何通过编程将它们过滤掉。您也可以通过路由来处理其中的一些问题。
HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes)
应该做些小动作,只是检查以确保它是一个公共方法。这也应该可以。我只是不太喜欢使用反射,尤其是在低层次的事情上。反射并不是最快的事情(或者我认为,也许有一天我真的应该对它进行基准测试)。@RobertMcKee我知道反射可能不是很多情况下最有效的解决方案。在我的例子中,我不会创建数百个链接,所以我对这里的反射非常满意;)
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));
}
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));
}