-1

作为一个学习项目,我有一个 MVC & Typescript 项目和一个 Web 2.0 & 实体框架项目,MVC 项目试图与 Web 2.0 项目对话,但我有一个奇怪的错误。

这是我的 Web API 2.0 播放器控制器:

 public class PlayerController : ApiController
{

    // GET api/<controller>/5
    public Player Get(int? id)
    {
        if (id == null || id == -1)
        {

            var player = new Player();
            LeaderBoardContext.Current.Players.Add(player);
            LeaderBoardContext.Current.SaveChanges();
            return player;
        }
        return LeaderBoardContext.Current.Players.FirstOrDefault(x => x.PlayerId == id);
    }


    // PUT: api/Scores/5
    [ResponseType(typeof(void))]
    public IHttpActionResult PostPlayer(LearningCancerAPICalls.Models.Player player)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var model = LeaderBoardContext.Current.Players.FirstOrDefault(x => x.PlayerId == player.PlayerId);
        LeaderBoardContext.Current.Entry<Player>(player).State = EntityState.Modified;

        try
        {
            LeaderBoardContext.Current.SaveChanges();
        }
        catch (DbUpdateConcurrencyException)
        {

        }
        return StatusCode(HttpStatusCode.NoContent);
    }
}

到目前为止,它经历了几次迭代,有一次它在文件顶部初始化了自己的数据库上下文,但在发布期间它神秘地为空。所以现在我正在使用我们在其他项目中使用的样式,如下所示:

public static LeaderBoardContext Current
    {
        get
        {
            try
            {
                //added because 'HttpContext.Current.Items["_EntityContext"] ' was mysteriously comming back null....
                if (HttpContext.Current.Items["_EntityContext"] == null)
                {
                    HttpContext.Current.Items["_EntityContext"] = new LeaderBoardContext();
                }

                var obj = HttpContext.Current?.Items["_EntityContext"] as LeaderBoardContext;
                return obj;
            }
            catch (Exception) //should only get here if using background task
            {
                return null;
            }
        }
    }

所以第一个奇怪的是在帖子中上下文坚持为空,但通过上面复杂的方法强制它不为空并没有太大改善这种情况。请注意,我现在放入的第一个 EF 调用与 GET 基本相同:

var model = LeaderBoardContext.Current.Players.FirstOrDefault(x => x.PlayerId == player.PlayerId);

我已经以两种样式调用了 GET(使用 -1,使用有效 ID)并且它工作正常,但是 POST 到目前为止导致了这个错误:

错误

我通常会将其与初始化错误的 EF 项目相关联,但 GET 有效!它确实做了它应该做的事情。我什至尝试过发布到具有不同型号的 EF 支架控制器并遇到同样的问题!

两者之间的主要区别(除了 GET/POST)是我调用它们的方式,这就是我使用 GET 的方式:

    var playerId = -1;
var activeUser:Player;
function initPlayerOnGameStart() {
    if (host === undefined) {
        host = 'http://localhost:52316';
    }
    if (playerId === undefined) {
        playerId = -1;
    }
    var uri = host + '/api/Player/' + playerId;
    jQuery.getJSON(uri).done(data => {
        activeUser = data;
        playerId = activeUser.PlayerId;
    });

}

在纯 Typescript Json 调用中。为了做 POST 我正在尝试使用 AJAX.Helper:

    @model LearningCancerAPICalls.Models.Player

<a id="contact-us">Share Score!</a>
<div id="contact-form" class="hidden" title="Online Request Form">
    @using (Ajax.BeginForm("", "", null, new AjaxOptions
    {
        HttpMethod = "POST", Url = "/api/Player",
        OnSuccess ="OnSuccess",
        OnFailure ="OnFailure" 
    }, new { id = "formId", name = "frmStandingAdd" }))
    {
        @Html.LabelFor(m => m.PlayerName);
        @Html.TextBoxFor(m => m.PlayerName);
        @Html.LabelFor(m => m.Email);
        @Html.TextBoxFor(m => m.Email);
        @Html.HiddenFor(m => m.PlayerId);
        @Html.Hidden( "PlayerId");
         <input type="submit" name="submit" value="Ok" />

    }
</div>

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script>
    function OnSuccess() {
        alert('Success');
    }
    function OnFailure(ajaxContext) {

        alert('Failure');
    }

</script>

我从打字稿中设置 PlayerID 的地方。这成功调用了帖子,但在第一次使用 EF 时崩溃。另一个奇特的事情是,如果我在帖子上进行调试。该模型似乎不正确,因为当我将鼠标悬停在它上面时,它显示为 Player 模型,没有铸造错误,但它不允许我扩展它的属性。如果我使用变量或即时窗口来检查变量,那么它们都很好。但我认为这值得一提。

稍后我将尝试一个纯 ajax 调用,看看它是否能解决它,但我不明白为什么 Ajax.helper 在这里会出错,它在技术上完成了它的工作,并且错误与我的模型无关可以看到。

更新 1 所以我尝试了纯 ajax 调用:

html:

 Name: <input type="text" name="fname" id="userName"><br />
        <button onclick="postJustPlayer()"> Ok </button>

打字稿

function postJustPlayer() {
    let level = jQuery("#chooseGridLevel").val();
    let name = jQuery("#userName").val();
    let uri = host + '/api/Player';
    let player: Player = <Player>{};


    player.Email = "Testing";
    player.PlayerName = name;
    jQuery.post(uri, player);
}

工作!??我不知道为什么纯 jQuery 可以工作,当然就 EF 而言,它确实做同样的事情?为什么 AJAX.helper 帖子会有所不同...

4

1 回答 1

0

解决了!这是一个真正的难题,只有在我深入研究网络数据(工具 ftw)时才解决。

对于其他网络新手,我将解释我是如何找到这个问题的路径的。在 Chrome 开发工具中有一个网络选项卡,它将显示您的网络请求和响应。因此,通过单击我的确定按钮后打开它,我可以看到我的纯 AJAX 调用:

在此处输入图像描述

然后,我可以将其与在我的 ajax 表单上单击“提交”时进行比较: 在此处输入图像描述

我将它们复制并粘贴到 KDiff3 中,其中突出显示了本地主机地址的一个非常重要的区别!

您会注意到在纯 ajax 请求中我指定了主机,这是因为正如我所提到的,我的 web api 项目和我的网站项目是分开的,因此它们位于不同的主机上!

所以,在现实中,AJAX 助手调用本不应该起作用,但就在我决定在我的网站项目中需要一个来自我的 API 项目的模型的前一天发生这种情况,当时我想“我可能不应该包含我的 API 项目作为我主要网站的参考,但只是现在......”。所以这会导致 API 调用错误的主机有效!当然,根本区别在于没有在该主机上设置 EF 。

如此可怜的老 ajax 助手让我对一个只有特殊类型的白痴设置才能导致的错误感到诅咒。更改 ajax 帮助程序以使用完整路径:

    @model LearningCancerAPICalls.Models.Player

<a id="contact-us">Share Score!</a>
<div id="contact-form" class="hidden" title="Online Request Form">
    @using (Ajax.BeginForm("", "", null, new AjaxOptions
    {
        HttpMethod = "POST", Url = "http://localhost:52316/api/Player",
        OnSuccess ="OnSuccess",
        OnFailure ="OnFailure" 
    }, new { id = "formId", name = "frmStandingAdd" }))
    {
        @Html.LabelFor(m => m.PlayerName);
        @Html.TextBoxFor(m => m.PlayerName);
        @Html.LabelFor(m => m.Email);
        @Html.TextBoxFor(m => m.Email);
        @Html.HiddenFor(m => m.PlayerId);
        @Html.Hidden( "PlayerId");
         <input type="submit" name="submit" value="Ok" />

    }
</div>

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script>
    function OnSuccess() {
        alert('Success');
    }
    function OnFailure(ajaxContext) {

        alert('Failure');
    }

</script>

解决了问题!感谢任何对此一头雾水的人,希望这个奇怪错误的分解对某人有用。

于 2017-09-08T09:13:13.123 回答