我正在写一个评论表,不能为我的生活弄清楚如何让我的控制器和视图互相交谈。这是使用knockout.js
在asp.net MVC中编写的这是我的代码:
Javascript:
var postApiUrl = '/api/WallPost/', commentApiUrl = '/api/Comment/';
function getTimeAgo(varDate) {
if (varDate) {
return $.timeago(varDate.toString().slice(-1) == 'Z' ? varDate : varDate + 'Z');
}
else {
return '';
}
}
// Model
function Post(data) {
var self = this;
data = data || {};
self.PostId = data.PostId;
self.Message = ko.observable(data.Message || "");
self.PostedBy = data.PostedBy || "";
self.PostedByName = data.PostedByName || "";
self.PostedByAvatar = data.PostedByAvatar || "";
self.PostedDate = getTimeAgo(data.PostedDate);
self.error = ko.observable();
self.PostComments = ko.observableArray();
self.newCommentMessage = ko.observable();
self.addComment = function () {
var comment = new Comment();
comment.PostId = self.PostId;
comment.Message(self.newCommentMessage());
return $.ajax({
url: commentApiUrl,
dataType: "json",
contentType: "application/json",
cache: false,
type: 'POST',
data: ko.toJSON(comment)
})
.done(function (result) {
self.PostComments.push(new Comment(result));
self.newCommentMessage('');
})
.fail(function () {
error('unable to add post');
});
}
if (data.PostComments) {
var mappedPosts = $.map(data.PostComments, function (item) { return new Comment(item); });
self.PostComments(mappedPosts);
}
self.toggleComment = function (item, event) {
$(event.target).next().find('.publishComment').toggle();
}
}
function Comment(data) {
var self = this;
data = data || {};
self.CommentId = data.CommentId;
self.PostId = data.PostId;
self.Message = ko.observable(data.Message || "");
self.CommentedBy = data.CommentedBy || "";
self.CommentedByAvatar = data.CommentedByAvatar || "";
self.CommentedByName = data.CommentedByName || "";
self.CommentedDate = getTimeAgo(data.CommentedDate);
self.error = ko.observable();
}
function viewModel() {
var self = this;
self.posts = ko.observableArray();
self.newMessage = ko.observable();
self.error = ko.observable();
self.loadPosts = function () {
//To load existing posts
$.ajax({
url: postApiUrl,
dataType: "json",
contentType: "application/json",
cache: false,
type: 'GET'
})
.done(function (data) {
var mappedPosts = $.map(data, function (item) { return new Post(item); });
self.posts(mappedPosts);
})
.fail(function () {
error('unable to load posts');
});
}
self.addPost = function () {
var post = new Post();
post.Message(self.newMessage());
return $.ajax({
url: postApiUrl,
dataType: "json",
contentType: "application/json",
cache: false,
type: 'POST',
data: ko.toJSON(post)
})
.done(function (result) {
self.posts.splice(0, 0, new Post(result));
self.newMessage('');
})
.fail(function () {
error('unable to add post');
});
}
self.loadPosts();
return self;
};
//textarea autosize
ko.bindingHandlers.jqAutoresize = {
init: function (element, valueAccessor, aBA, vm) {
if (!$(element).hasClass('msgTextArea')) {
$(element).css('height', '1em');
}
$(element).autosize();
}
};
ko.applyBindings(new ViewModel());
这些是我的两个控制者:
public class CommentController : ApiController
{
private string imgFolder = "/Images/profileimages/";
private string defaultAvatar = "user.png";
private WallEntities db = new WallEntities();
// POST api/Comment
public HttpResponseMessage PostPostComment(PostComment postcomment)
{
postcomment.CommentedBy = WebSecurity.CurrentUserId;
postcomment.CommentedDate = DateTime.UtcNow;
ModelState.Remove("postcomment.CommentedBy");
ModelState.Remove("postcomment.CommentedDate");
if (ModelState.IsValid)
{
db.PostComments.Add(postcomment);
db.SaveChanges();
var usr = db.UserProfiles.FirstOrDefault(x => x.UserId == postcomment.CommentedBy);
var ret = new
{
CommentedBy = postcomment.CommentedBy,
CommentedByName = usr.UserName,
CommentedByAvatar = imgFolder + (String.IsNullOrEmpty(usr.AvatarExt) ? defaultAvatar : postcomment.CommentedBy + "." + postcomment.UserProfile.AvatarExt),
CommentedDate = postcomment.CommentedDate,
CommentId = postcomment.CommentId,
Message = postcomment.Message,
PostId = postcomment.PostId
};
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, ret);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = postcomment.CommentId }));
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
和
[Authorize]
public class WallPostController : ApiController
{
private string imgFolder = "/Images/profileimages/";
private string defaultAvatar = "user.png";
private WallEntities db = new WallEntities();
// GET api/WallPost
public dynamic GetPosts()
{
var ret = (from post in db.Posts.ToList()
orderby post.PostedDate descending
select new
{
Message = post.Message,
PostedBy = post.PostedBy,
PostedByName = post.UserProfile.UserName,
PostedByAvatar = imgFolder + (String.IsNullOrEmpty(post.UserProfile.AvatarExt) ? defaultAvatar : post.PostedBy + "." + post.UserProfile.AvatarExt),
PostedDate = post.PostedDate,
PostId = post.PostId,
PostComments = from comment in post.PostComments.ToList()
orderby comment.CommentedDate
select new
{
CommentedBy = comment.CommentedBy,
CommentedByName = comment.UserProfile.UserName,
CommentedByAvatar = imgFolder + (String.IsNullOrEmpty(comment.UserProfile.AvatarExt) ? defaultAvatar : comment.CommentedBy + "." + comment.UserProfile.AvatarExt),
CommentedDate = comment.CommentedDate,
CommentId = comment.CommentId,
Message = comment.Message,
PostId = comment.PostId
}
}).AsEnumerable();
return ret;
}
// POST api/WallPost
public HttpResponseMessage PostPost(Post post)
{
post.PostedBy = WebSecurity.CurrentUserId;
post.PostedDate = DateTime.UtcNow;
ModelState.Remove("post.PostedBy");
ModelState.Remove("post.PostedDate");
if (ModelState.IsValid)
{
db.Posts.Add(post);
db.SaveChanges();
var usr = db.UserProfiles.FirstOrDefault(x => x.UserId == post.PostedBy);
var ret = new
{
Message = post.Message,
PostedBy = post.PostedBy,
PostedByName = usr.UserName,
PostedByAvatar = imgFolder + (String.IsNullOrEmpty(usr.AvatarExt) ? defaultAvatar : post.PostedBy + "." + post.UserProfile.AvatarExt),
PostedDate = post.PostedDate,
PostId = post.PostId
};
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, ret);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = post.PostId }));
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
我不确定从哪里链接我的模型。我尝试了ko.applyBindings(new ViewModel());但这似乎没什么用。
我的观点:
@{
ViewBag.Title = "Wall";
}
<h2>Facebook Style Wall Posting and Commenting</h2>
<div class="publishContainer">
<textarea class="msgTextArea" id="txtMessage" data-bind="value: newMessage, jqAutoresize: {}" style="height:3em;" placeholder="What's on your mind?"></textarea>
<input type="button" data-url="/Wall/SavePost" value="Share" id="btnShare" data- bind="click: addPost">
</div>
<ul id="msgHolder" data-bind="foreach: posts">
<li class="postHolder">
<img data-bind="attr: { src: PostedByAvatar }"><p><a data-bind="text: PostedByName"></a>: <span data-bind=" html: Message"></span></p>
<div class="postFooter">
<span class="timeago" data-bind="text: PostedDate"></span> <a class="linkComment" href="#" data-bind=" click: toggleComment">Comment</a>
<div class="commentSection">
<ul data-bind="foreach: PostComments">
<li class="commentHolder">
<img data-bind="attr: { src: CommentedByAvatar }"><p><a data- bind="text: CommentedByName"></a>: <span data-bind=" html: Message"></span></p>
<div class="commentFooter"> <span class="timeago" data-bind="text: CommentedDate"></span> </div>
</li>
</ul>
<div style="display: block" class="publishComment">
<textarea class="commentTextArea" data-bind="value: newCommentMessage, jqAutoresize: {}" placeholder="write a comment..."></textarea>
<input type="button" value="Comment" class="btnComment" data-bind="click: addComment" />
</div>
</div>
</div>
</li>