Umbraco 在后台找不到路由

Umbraco cannot find the route in backoffice

我在我的项目中使用了 Umbraco 7.3。我创建了一个自定义数据类型,但是当我想在这里调用 SurfacecontrollerHelloSurfaceControllerHello2SurfaceController 时,我在 umbraco 后台收到一个错误,说 Request error: The URL returned a 404 (not found):

我研究了一些关于路由的文章,但我无法解决我的问题。不知道哪里做错了

我该如何解决这个问题?

Reply.controller.js:

angular.module("umbraco")
.controller("Reply.controller", function ($scope, $http) {
    $scope.SendReply = function () {
        var sendTo = $("#Email").val();
        var textMessage = $("#TextMessage").val();

        $scope.xxx = "I'm here!";
        var data = { SendTo: sendTo, TextMessage: textMessage };
        //   ~/Hello2Surface/ReplyMessage  ---> Cannot find this URL
        $http.post("~/App_Plugins/Reply/HelloSurface/ReplyMessage") // Can not find this URL
            .then(function (response) {
                alert("YES!");
                //TODO: 
            });
    }
});

SurfaceController

 namespace Jahan.Nuts.Web.Mvc.UmbracoCms.App.App_Plugins.Reply
 {
    public class HelloSurfaceController : SurfaceController
    {
        [HttpPost][ChildActionOnly]
        public ActionResult ReplyMessage()
        {
            //TODO: how should be write this method that be proper for getting data from angularjs?
            return null;
        }
    }
 }

package.manifest

{
propertyEditors: [
    {
        alias: "Send.Reply",
        name: "Send Reply",
        editor:{
            view:"~/App_Plugins/Reply/Reply.html"
        },
    }
]
,
javascript:[
    '~/App_Plugins/Reply/Reply.controller.js'
]
}

Reply.html

<div ng-controller="Reply.controller">
<div style="width: 100%;">
    <input type="button" value="Send Reply" title="SendReply" name="Send Reply" ng-click="SendReply()" />
</div>
<div>
    <input type="text" ng-model="xxx" name="message" />
</div>

Error in umbraco backoffice:

仔细查看文档 - 特别是基于插件的 SurfaceControllers 部分:

https://our.umbraco.org/documentation/Reference/Routing/surface-controllers

尝试这样做(注意 PluginController 属性):

namespace Jahan.Nuts.Web.Mvc.UmbracoCms.App.App_Plugins.Reply
{
    [PluginController("Reply")]
    public class HelloSurfaceController : SurfaceController
    {
        [HttpPost][ChildActionOnly]
        public ActionResult ReplyMessage()
        {
            //TODO: how should be write this method that be proper for getting data from angularjs?
            return null;
        }
    }
 }

其他注意事项:

  • 您不再需要在控制器名称中包含 "Surface" - 只需将其命名为 HelloController 即可。
  • 如果您将 SurfaceController 与 AngularJS 一起使用,请不要将其用于 Api 调用 - 最好使用 UmbracoApiController。查看 https://our.umbraco.org/documentation/Reference/Routing/WebApi/ 了解更多信息(包括关于预期 Api 端点所在位置的注释)
  • 您可能还想重新定位您的控制器,使其位于更传统的位置。就算是Plugin Controller放在~/Controllers目录下也没问题

编辑: 添加了 "correct" 方法:

如上所述,要实现 UmbracoApiController,您需要一个像这样的 class - 请注意,如果不需要,您可以使用 UmbracoApiController担心授权:

namespace Jahan.Nuts.Web.Mvc.UmbracoCms.App.App_Plugins.Reply
{
    [PluginController("Reply")]
    public class HelloApiController : UmbracoAuthorizedApiController
    {
        public void PostReplyMessage(string to, string message)
        {
            // TODO: process your message and then return something (if you want to).

        }
    }
 }

然后在AngularJS中设置这样的资源:

function replyResource($q, $http, umbDataFormatter, umbRequestHelper) {
    var replyResource = {
        sendMessage: function (sendTo, msg) {    
            return umbRequestHelper.resourcePromise(
                           $http.post("Backoffice/Reply/HelloApi/PostReplyMessage?" +
                                umbRequestHelper.dictionaryToQueryString(
                                   [{ to: sendTo }, { message: msg }])),
                           'Failed to send message to ' + sendTo + ': ' + msg);
        }
    };


    return replyResource;
}

angular.module('umbraco.resources').factory('replyResource', replyResource);

最后,您的实际视图控制器可以按如下方式使用它:

angular.module("umbraco")
.controller("Reply.controller", function ($scope, $http, $injector) {

    // Get a reference to our resource - this is why we need the $injector specified above
    replyResource = $injector.get('replyResource');

    $scope.SendReply = function () {
        // You really shouldn't use jQuery here - learn to use AngularJS Bindings instead and bind your model properly.
        var sendTo = $("#Email").val();
        var textMessage = $("#TextMessage").val();

        replyResource.sendMessage(sendTo, textMessage)
            .then(function (response) {
               // Success
            }, function (err) {
               // Failure
            });
        }
    };
});

可能里面有一些错误;我主要是凭记忆完成的——特别是,您可能需要研究将 post 数据发送到 Api 控制器的最佳方法——它不太可能只接受这样的两个参数。

要获得更完整的示例,请考虑查看 Umbraco MemberListView 插件的代码:https://github.com/robertjf/umbMemberListView

此外,您真的应该阅读上面列出的 ASP.Net MVC 基础知识和 SurfaceControllers 和 APIControllers 的 Umbraco 文档。

从 URL 中删除 "Surface" 并包含 "backoffice":

 angular.module("umbraco")
    .controller("Reply.controller", function ($scope, $http) {
        $scope.SendReply = function () {
            var sendTo = $("#Email").val();
            var textMessage = $("#TextMessage").val();

            $scope.xxx = "I'm here!";
            var data = { SendTo: sendTo, TextMessage: textMessage };
            //   ~/Hello2Surface/ReplyMessage  ---> Cannot find this URL
            $http.post("backoffice/Reply/Hello/ReplyMessage") // Can not find this URL
                .then(function (response) {
                    alert("YES!");
                    //TODO: 
                });
        }
    });

此外,我建议使用 UmbracoAuthorizedController 而不是表面控制器,因为登录用户在后端使用它,因此保持它的安全是明智的。

所以你的控制器应该看起来像这样:

[PluginController("Reply")]
namespace Jahan.Nuts.Web.Mvc.UmbracoCms.App.App_Plugins.Reply
 {
    public class HelloApiController : UmbracoAuthorizedJsonController
    {
        public [Model-to-be-returned-to-angular] ReplyMessage()
        {
            //sql query etc to populate model
            //return model
        }
    }
 }