how to use mvc4 model value in knockout viewmodel js - asp.net-mvc

I am using Knockout with ASP.NET MVC here is my View which is populated by MVC controller
HTML
<html>
<input type="text" data-bind="value:Name" />
<script src="/Scripts/ViewModel.js"></script>
</html>
Controller
public actionresult xyz(){
var myModel = new FiestModel();
myModel.Name = "James";
return view(myModel);
}
ViewModel.Js
function mymode(){
var self = this ;
self.Name = ko.observable('#Model.Name');
}
after doing all of this when my page render my input doesn't have the specified value James .
Update
I tell you guys about the whole scenario , in my application a user click on signup with facebook button and facebook return user back to my xyz action method , now i want to show the username in xyz view . So how can i do this with api because #Anders said me to do this by Web APi .
Thanks in advance .

You shouldnt mix server side MVC and client side MVVM.
Move the model population to a WebAPI controller method.
Load the data using jQuery.getJSON or other framework for Ajax
You can also use ko.mapping to map the server data into ViewModels
edit: code in ViewModel.js have to be moved to the cshtml file if oyu want to use
#Mode.Name, but please dont do it.
Update
Something along the lines
[HttpGet]
public FiestModel xyz() {
return new FiestModel("James");
}
With mapping plugin something like
ViewModel = function(data) {
ko.mapping.fromJS(data, {}, this);
};
$.getJSON("api/myController/xyz", null, function(data) {
ko.applyBindings(new ViewModel(data));
});

Try with something like on JS:
function myModel(){
var data = #(Html.Raw(Json.Encode(Model)));
this.Name = ko.observable(data.Name);
}
Then you bind your view model:
ko.applyBindings(new myModel());

Related

ASP.NET MVC - Execute controller action without redirecting

I am trying to execute an action on a controller without redirecting to the associated view for that action. For a good example of what I am trying to achieve take a look at the music.xbox.com website. When you add a song to a selected playlist from a popup menu - the page just shows a notification without any redirect or refresh. how is this possible?
What I have is the following:
I have a _playlistPopupMenu partial view that renders the list of playlists as follows:
_PlaylistPopupMenu
#model List<OneMusic.Models.GetPlaylists_Result>
#if (Model.Count > 0)
{
<li style="height:2px" class="divider"></li>
foreach (var item in Model)
{
<li style="height:30px">#Html.DisplayFor(p => item.Name)
#Html.ActionLink(item.Name, "AddSong", "Playlist", new { playlistId = #item.PlaylistId, songId = 1 }, "")
</li>
}
}
The PlaylistController AddSong action is as follows:
public PartialViewResult AddSong(int? playlistId, int? songId)
{
if (ModelState.IsValid)
{
db.AddSongToPlaylist(playlistId, songId);
db.SaveChanges();
return PartialView("_AddToPlaylist", "");
}
return PartialView("_AddToPlaylist", "");
}
I am struggling with what to put in the _AddToPlaylist partial view which I think I need to be able to display a notification of some kind (Possiblly using PNotify add in for Bootstrap). MVC wants to always redirect to ../Playlist/AddSong?playlistId=1&songId=1
Any ideas on how to complete this last part of the problem would be great.
If you don't want "full page reloads" then you need to approach the problem slightly differently, using javascript to alter the page dynamically. A library such as JQuery might make manipulating the DOM a little easier.
Display the popup dynamically using javascript.
When the user hits OK/Submit on the popup, post the data back to the server using javascript, and have the controller you are posting to return some HTML.
Append the returned HTML block (partial view) to an existing div containing playlist tracks.
The most difficult part of this is the asynchronous post. Help with updating a div without reloading the whole page can be found in this question.
EDIT - Example
If you have a controller action (accepting POSTs) with the URL myapp.com/PlayList/AddSong/, then you'd set up JQuery to post to this URL. You'd also set up the data property with any form data which you'd like to post, in your case you'd add playistId and songId to the data property.
You'd then use the result of the AJAX query (HTML) and append it to the existing playlist HTML on the page. So assuming that you want to append the partial view's HTML to a div with ID playlistDiv, and assuming that your partial view returns HTML which is valid when appended to the existing playlist, then your javascript will look something like this:
var data = { playlistId: 1, songId: 1 };
$.ajax({
type: "POST",
url: 'http://myapp.com/PlayList/AddSong/',
data: data,
success: function(resultData) {
// take the result data and update the div
$("#playlistDiv").append(resultData.html)
},
dataType: dataType
});
Disclaimer: I can't guarantee that this code will work 100% (unless I write the program myself). There may be differences in the version of JQuery that you use, etc, but with a little tweaking it should achieve the desired result.
using System.Web.Mvc;
using System.Web.Mvc.Html;
public ActionResult Index()
{
HtmlHelper helper = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "Index"), new ViewDataDictionary(), new TempDataDictionary(), new System.IO.StringWriter()), new ViewPage());
helper.RenderAction("Index2");
return View();
}
public ActionResult Index2(/*your arg*/)
{
//your code
return new EmptyResult();
}
in your controller you must add bottom code:
public ActionResult Index(string msg)
{
if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com"))
{
string html = "";
using (System.Net.WebClient client = new System.Net.WebClient())
{
client.Encoding = Encoding.UTF8;
html = client.DownloadString("https://NewExampleUrl.com/first/index?id=1");
}
Response.Write(html);
}
...
}
your view must be empty so you add bottom code
#{
ViewBag.Title = "sample title";
if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com"))
{
Layout = null;
}else
{
Layout ="~/Views/Shared/_Layout.cshtml"
}
}
#if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com")==false)
{
before view like :
<div>hello world</div>
}

How to Prevent Page refresh on select change for dropdownlist in MVC

I have a dropdownlist in my razor view MVC like
#Html.DropDownListFor(n => n.EMP_ID, (SelectList)ViewBag.EmployeeList, new { #id = "ddlemployee" },"---choose an Employee Name--").
I have applied select change event to drop-down using jquery, when select Employee name getting Employee names and realted data, but problem is when i select a value in drop-down, dropdownlist setting again set to default first value,
It is not sticking to particular selected value, in terms of Asp.net terminology, how to prevent postback to dropdownlist?
//Redirected to Controller
<script>
$(document).ready(function () {
$("#ddlemployee").change(function () {
location.href ='#Url.Action("GetEmployeeDetails", "Employer")'
});
});
</script>
//Action Method in Employer Controller
public ActionResult GetEmployeeDetails(Timesheetmodel model)
{
try
{
ViewBag.EmployeeList = objts.getEmployeeNames();
var emps = from n in db.TIMESHEETs
where n.RES_ID == model.EMP_ID
select n;
int count = emps.Count();
foreach (TIMESHEET ts in emps)
{
model.PROJ_ID = ts.PROJ_ID;
model.SUN_HRS = ts.SUN_HRS;
model.MON_HRS = ts.MON_HRS;
model.TUE_HRS = ts.TUE_HRS;
model.WED_HRS = ts.WED_HRS;
model.THU_HRS = ts.THU_HRS;
model.FRI_HRS = ts.FRI_HRS;
model.SAT_HRS = ts.SAT_HRS;
}
}
catch (Exception ex)
{
throw ex;
}
return View("Timesheet", model);
}
ASP.Net Webforms achieve StateFullness by using Some thing called ViewState
It is implemented as hidden fields in the page to hold data between requests.
This way , asp.net webforms achieves post back mechanism and was able to hold values in bewteen the requests.
Since Http is a stateless protocol , which means it has no relation between requests.
View State is absent in ASP.Net MVC.
So, you have to stop postback by partially posting back . Which means that you need to send an asynchronous request with out refreshing whole page.
It is possible by using AJAX. You can either use
MVC Ajax or Jquery Ajax.
By using AJax, we can eliminate the post back and then do the partial post back.
Solution:
$("#dropdownid").change(function(event e)
{
//Make your ajax request here..
});
Hope this helps
Updated:
$("#dropdownid").change(function () {
$.ajax({
type: "post",
contentType: "application/json;charset=utf-8",
url: /*Your URL*/,
success: function (data) {
//do your callback operation
}
});
});
Got it.
Passing Empid as querystring from jquery like:
<script>
$(document).ready(function () {
$("#ddlemployee").change(function () {
debugger;
var empid = $("#ddlemployee").val();
location.href = '#Url.Action("GetEmployeeDetails", "Employer")?empid=' + empid ;
});
});
</script>
and assign "empid " to model "Empid" in Action method before foreach loop like
model.EMP_ID = empid;//in Controller Action Method before foreachloop of my code
// and this model.EMP_ID binded to dropdownlist.
this EMP_ID passes same id to dropdownlist which was selected. Thats it.

MVC3 - RenderPartial inside RenderSection not working

I'm working on an MVC3/Razor page, and in my _layout I have
#RenderSection("relatedBooksContainer", false)
In another page I use that section with:
#section relatedBooksContainer
{
#{ Html.RenderPartial("~/Views/Shared/Bookshelf.cshtml", Model.Books);}
}
This doesn't work. From what I've read, RenderSection will only ever go one layer deep - it has no concept of the Html.RenderPartial in the related section and will just return a blank area. The workaround I read at http://forums.asp.net/t/1590688.aspx/2/10 is to use RenderPage and commit the returned HTML to a string, then outout that string in the render section...which works! That is, until I pass a model to the partial page, then it throws an error saying:
The model item passed into the
dictionary is of type
'TheBookshelf.ViewModels.BookshelfViewModel',
but this dictionary requires a model
item of type
'System.Collections.Generic.List`1[TheBookshelf.EntityModel.Book]'.
Anyone have any idea why this might be happening? Are there any other ways to achieve this?
Try the #Html.Partial instead
#section relatedBooksContainer
{
#{ Html.Partial("~/Views/Shared/Bookshelf.cshtml", Model.Books);}
}
The error message is regarding the type and return type of the Bookshelf from the model.
public IEnumerable<Book> Bookshelf()
{
var q = from book in bookshelf
select book;
IEnumerable<Book> myBooks = q.ToList<Book>();
return myBooks;
}
did the solution in the provided link work for you?
I couldn't get it to work. That is I couldn't get ViewData["MainView"] to pass the data from Layout.cshtml to partialview. This aparently is a feature as every view is supposed to have it own ViewData obj. It seems ViewData is not global like I have thought. So what I get in ViewData["MainView"] from Layout in my partial view is null......I eventually found a work around for this and was able to pass the page reference from Layout to Partialview via a #Html.Action call from Layout -> Controller -> PartialView. I was able to get my partialview to access and write to the correct rendersection. However I want to call the same partialview many times in my Layout.cshtml. A subsequent call to the same Partialview again in the Layout, does not work, as the reference to layout has changed since the first call and rendersection update. So the code looks like this:
Layout.cshtml:
#RenderSection("Top", false)
#Html.Action("Load", "Home", new { viewname = "_testPartialView", pageref = this })
#Html.Action("Load", "Home", new { viewname = "_testPartialView", pageref = this })
Partial View:
#Model Models.testModel
#Model.Content
#{
var md = (System.Web.Mvc.WebViewPage)#Model.pageRef;
#*This check fails in subsequent loads as we get null*#
if(md.IsSectionDefined("Footer")) {
md.RenderSection("Footer");
}
else {
md.DefineSection("Footer", () => { md.WriteLiteral("<div>My Contents</div>"); });
}
}
}
controller:
public ActionResult Load(string viewname, System.Web.Mvc.WebViewPage pageRef)
{
var model = new Models.testModel { Content = new HtmlString("time " + i++.ToString()), pageRef = pageRef };
return PartialView(viewname, model);
}

Dynamically loading partial view

For a project I need a dynamic way of loading partial views, preferably by jquery / ajax.
Here's the functionality I require:
User enters form. A dropdownlist is shown and a generic partial view is rendered with some input controls.
User selects a different value in the dropdown
The partial view refreshes. Based on the value of the dropdown, it should load the partial view. Some values have custom views associated with them (I could name them with the primary key for instance), others don't. When there's no custom view; it should load the default. When there is one, it should of course load the custom one.
And this should all be ajaxified when possible.
I have read some things about dynamically loading partials, but I wanted to repost the complete case so I can find the best solution for this specific case.
Assuming you have a dropdown:
#Html.DropDownListFor(
x => x.ItemId,
new SelectList(Model.Items, "Value", "Text"),
new {
id = "myddl",
data_url = Url.Action("Foo", "SomeController")
}
)
you could subscribe for the .change() event of this dropdown and send an AJAX request to a controller action which will return a partial and inject the result into the DOM:
<script type="text/javascript">
$(function() {
$('#myddl').change(function() {
var url = $(this).data('url');
var value = $(this).val();
$('#result').load(url, { value: value })
});
});
</script>
And place a DIV tag where you want the partial view to render in your host view:
<div id="result"></div>
and inside the Foo action you could return a partial view:
public ActionResult Foo(string value)
{
SomeModel model = ...
return PartialView(model);
}
You should handle the value changed event of the combobox, get the Id selected, then use ajax to call a server action, passing the selected Id.
The server action will return the corresponding view. At client side you populate the returned view to a region on the page.
For example of the server side action:
public ActionResult GetView(int id)
{
switch (id)
{
case 1:
return View("View1", model1);
break;
case 2:
return View("View2", model2);
break;
default:
return View("Default", modelDefault);
}
}

jQuery post to another controller

If I have a Controller called "HomeController" and I'm on the Index page of that controller, how can I do a jQuery Ajax post to another controller.
I tried the below,
$.post("/DetailedQuote/jQueryGetDetailedQuote", { productCode: "LPJ" }, function(newHTML) {
alert(88);
});
I have a DetailedQuoteController.
I have also tried;
post("DetailedQuote/
post("DetailedQuote.aspx/
post("/DetailedQuote.aspx/
post("/DetailedQuoteController/
post("DetailedQuoteController/
post("DetailedQuoteController.aspx/
post("/DetailedQuoteController.aspx/
And still no joy.
I should also mention that this is running a Hybrid WebForms and MVC site on IIS 6.
EDIT
The error that is being returned in error: is "error" so I assume that's maybe a 404.
In fact, it is a 404. I just checked.
This should work:
public class DetailedQuoteController : Controller
{
[HttpPost]
public ActionResult GetDetailedQuote(string productCode)
{
return Json(new { Code = productCode, Quote = 123 });
}
}
And to invoke it first declare a global javascript variable containing the address of this controller somewhere inside the view:
var quoteAddress = '<%= Url.RouteUrl(new { controller = "DetailedQuote", action = "GetDetailedQuote" }) %>';
And finally call the method:
$(function() {
$.post(quoteAddress, { productCode: 'LPJ' }, function(json) {
alert(json.Quote);
});
});
There doesn't appear to be anything wrong with your jQuery command, so the most obvious place to start looking is in the controller itself. Things to check would be:
Does your Controller action return a Json response (e.g. public JsonResult jQueryGetDetailedQuote)?
Are you using the Json() method to return your object?
Do you have your action decorated with the [HttpPost] attribute?
Perhaps you could post part of your controller code as well?
I notice that in your jQuery method you're calling an action called jQueryGetDetailedQuote. If your intention is purely to just GET a result, then perhaps you should use jQuery's $.get() or $.getJSON() functions instead?

Resources