我正在尝试将Model
中OnGetAsync
处的值从另一个Razor Page
分配给Model
进行一些数据验证,然后将它们分配回OnPostAsync
上的实际NullReferenceException
用于保存数据。
在此行Input.TestName = TestData.TestName;
上出现public class TestData
{
[Key]
public int TestID { get; set; }
public string TestName { get; set; }
}
错误
private readonly Test.Models.TestContext _context;
public EditModel(Test.Models.TestContext context)
{
_context = context;
}
[BindProperty]
public TestData TestData { get; set; }
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[Required, MaxLength(50), MinLength(3)]
public string TestName { get; set; }
}
public async Task<IActionResult> OnGetAsync(int? id)
{
TestData = await _context.TestData.FirstOrDefaultAsync(m => m.TestID == id);
Input.TestName = TestData.TestName; //Error Occurs here. TestData.TestName has value while debug.
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
TestData.TestName = Input.TestName;
_context.Attach(TestData).State = EntityState.Modified;
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
页面模型
TestName
我在InputModel class
之外尝试了class
,但效果很好,但是我有很多类似的属性可以使用。所以我想将它们放在一个import React, { PropTypes } from 'react';
import { Link, browserHistory } from 'react-router';
import * as DataConnectionAction from '../../actions/dataconnectionAction.jsx';
import DataConnectionStore from '../../store/dataconnectionstore.jsx';
class DataSource extends React.Component {
constructor(props) {
super(props);
this.state = {
datasourcelist: [],
};
this._dataconnectionStoreChange = this._dataconnectionStoreChange.bind(this);
}
componentWillMount() {
DataConnectionStore.on('change', this._dataconnectionStoreChange);
}
componentWillUnmount() {
DataConnectionStore.removeListener('change', this._dataconnectionStoreChange);
}
componentDidMount() {
DataConnectionAction._getDataSourcesList();
}
_dataconnectionStoreChange(type) {
if (type == 'DataSourcesList') {
let datasourcelist = DataConnectionStore._getDataSourceList() || {};
this.setState({ datasourcelist: datasourcelist.dataconnections });
}
}
DataSourceView(el) {
let data = {
id: el.dataConnectionName
}
}
_handleSearchChange(e) {
let value = e.target.value;
let lowercasedValue = value.toLowerCase();
let datasourcedata = this.state.datasourcelist;
let datasourcelist = datasourcedata && datasourcedata.filter(el => el.dataConnectionName.toLowerCase().includes(lowercasedValue));
this.setState({ datasourcelist });
}
DataSourcesCardUI() {
let datasourcedata = this.state.datasourcelist;
return (
datasourcedata && datasourcedata.map((el) =>
<div key={el.key}>
<div className="col-md-3 topadjust">
<div className="panel panel-default datasource_panel ">
<div className="panel-heading">
<h5 className="panel_title"><i className="fa fa-database"></i> {el.dataConnectionName}</h5>
</div>
<Link className="panel-body" onClick={this.DataSourceView.bind(this, el)}>
<div className="datasource_txt text-center">
<h6>{el.databaseHost}</h6>
<h6>{el.dataConnectionType} </h6>
<p>{el.createdDate}</p>
</div>
</Link>
</div>
</div>
</div>
)
);
}
render() {
return (
<div>
<section className="content_block">
<div className="container-fluid">
<div className="row dashboard_list">
{this.DataSourcesCardUI()}
</div>
</div>
</section>
</div>
);
}
}
export default DataSource;
请在这里建议我所缺少的内容。
答案 0 :(得分:2)
在问题中已确认TestData.TestName
在调试器中具有值时,应将注意力转移到Input.TestName
上。更具体地说,这很可能意味着Input
属性本身就是null
,这将导致您的NullReferenceException
。
这也是有道理的。调用OnPostAsync
时,ASP.NET Core尝试使用请求中的数据绑定到您的Input
属性,这将导致它为您创建InputModel
的实例。可以通过使用[BindProperty]
属性本身上的Input
属性来启用此功能。
但是,当调用OnGetAsync
时,不会发生相同的过程。默认情况下,[BindProperty]
仅触发非GET请求来执行此绑定,这意味着Input
调用中的OnGetAsync
将是null
(这是默认值,仅供参考)类型的属性)。
要解决此问题,请在尝试设置其OnGetAsync
值之前,先更新您的Input
实现以创建自己的TestName
实例。这是实现该目标的一种方法:
public async Task<IActionResult> OnGetAsync(int? id)
{
TestData = await _context.TestData.FirstOrDefaultAsync(m => m.TestID == id);
Input = new InputModel { TestName = TestData.TestName };
return Page();
}
还值得记住的是,如果ID不匹配,则您对FirstOrDefaultAsync
的呼叫会将TestData
设置为null
,这将为您提供不同的NullReferenceException