视图将某些属性作为null返回给Controller

时间:2019-03-01 19:24:17

标签: asp.net-mvc asp.net-core web-applications

这是我的观点:

    @model MediaShuttleCoreWebApp.Models.MediaShuttleAPI.ApiResponse.TransferLinkResponseContainer

@{
    ViewData["Title"] = "CreateDownloadToken";
}

<h2>CreateDownloadToken</h2>


<div class="container we myBorder">
    <h3 class="text-center display-4 myBorder"> Media Shuttle </h3>
    @if (Model.User == null)
    {

    }
    <a class="btn btn-primary btn-lg" href="@Url.Action("SendEmail","MediaShuttle", Model)"
       role="button">Create Download Token</a>
    <p>Email: @Model.User.Email</p>
</div>

现在,当用户单击作为“标签”的“按钮”时,它会将模型发送回控制器。但是我注意到它返回2个属性为NULL,其余的则填充了最初传递给View()的值。

这是传递给View()的模型:

namespace MediaShuttleCoreWebApp.Models.MediaShuttleAPI.ApiResponse
{
[DataContract]
    public class TransferLinkResponseContainer
{        
    [DataMember(Name = "id")]
    public string Id { get; set; }

    [DataMember(Name = "url")]
    public string Url { get; set; }

    [DataMember(Name = "createdOn")]
    public DateTime CreatedOn { get; set; }

    [DataMember(Name = "expiresOn")]
    public DateTime ExpiresOn { get; set; }

    [DataMember(Name = "user")]
    public User User { get; set; }

    [DataMember(Name = "grants")]
    public IList<string> Grants { get; set; }

    [DataMember(Name = "destinationPath")]
    public string DestinationPath { get; set; }

    [DataMember(Name = "notifications")]
    public IList<Notification> Notifications { get; set; }
}
}

以NULL返回的2个属性是:

public User User { get; set; }
public IList<Notification> Notifications { get; set; }

请注意,这两个属性不是您的普通字符串,int或datetime类型。因此,场景是当我将模型从Controller传递到View()时,我有数据,但是当我将模型从View()传递到Controller时,在“ Url.Action”中,只有一些属性填充有原始属性。价值观。知道为什么会这样吗?我到处都看过了,但是没有任何东西可以真正解释为什么我的2个属性以null返回。

我考虑过只创建一个具有两个不同类型的属性的ViewModel并将它们设置为字符串。

这是User属性的类:

    [DataContract]
public class User
{
    [DataMember(Name = "email")]
    public string Email { get; set; }
}

它只包含一个字符串。

也接受任何建议。但是我真的很想了解将模型返回给Controller时发生了什么,为什么这两个属性返回为null。

1 个答案:

答案 0 :(得分:0)

答案在href标签中。例如,我将仅使用模型的一部分来显示导致此行为的原因。

public class TransferLinkResponseContainer
{
    public string Url { get; set; }

    public User User { get; set; }

    public IList<string> Grants { get; set; }
}

public class User
{
    public string Email { get; set; }
}

然后让实例化模型如下

var model = new TransferLinkResponseContainer
{
    Url = "url",
    User = new User
    {
        Email = "test@test.com"
    },
    Grants = new List<string> { "grant1", "grant2" },
};

使用此设置href将包含以下值

"/MediaShuttle/SendEmail?Grants=grant1&Grants=grant2&Url=url&User=ASPNETCoreDeploy.Controllers.User"

我们可以看到它包含所有Grants值,Url值和User类的全名(在您的项目中有所不同)。表示User对象显然是无效的字符串。模型绑定程序无法根据请求绑定User字符串中的"ASPNETCoreDeploy.Controllers.User"属性,因此Usernull的原因。

为什么会这样?显然,Url.Action只是为传递的模型的每个属性调用ToString方法(或迭代集合并为每个元素调用ToString)。可以重写此方法,但是它对正确绑定对象没有帮助。让我们看看如果执行此操作会发生什么。为ToString覆盖User

public class User
{
    public string Email { get; set; }

    public override string ToString()
    {
        return Email;
    }
}

href的值变为

"/MediaShuttle/SendEmail?Grants=grant1&Grants=grant2&Url=url&User=test@test.com"

看起来更好,但是无论如何您都会得到User等于null。要正确绑定User对象,您需要遵循以下模板User.Prop1=val1&User.Prop2=val2...,依此类推。您的情况下,以下网址将按预期工作

"/MediaShuttle/SendEmail?Grants=grant1&Grants=grant2&Url=url&User.Email=test@test.com"

但是据我所知,Url.Action是不可能实现的。这就是为什么传递复杂对象的更可取的方式是使用<form>标签。