Best practice for using web services (ASP.MVC) - asp.net-mvc

Basically what I have is web services returning data in xml format. Once I do a call to a webservice to retrive data from web service function (GetUserList) i want to take that data and then dymaically display (no postback) the resulting information. I know several ways of doing this:
webservice sends data back to javascript, javascript then parses, replaces strings or text inside a div or child, or take the information retrieved and then put it into html table format through javascript.
Those are some of the idea's i've came up with, does anyone know the best practice to do this?
Using ASP.MVC (.Net)

It depends entirely on your application. I've both had the action return pure data (usually JSON, not XML) and handled the display in the client and had the action return a partial view. For most complex display scenarios, I think the partial view route is easiest. Essentially, you are returning just the portion of the page (HTML) that is going to be updated. You use javascript in the AJAX callback handler to replace the appropriate element(s) on the page with the HTML you get back from the server. Note that you need to be careful with event handler binding when you do this -- it's almost always the right thing to do to use live handlers in jQuery 1.4+ and rebind all but click handlers in jQuery 1.3.
Example: Assumes that you are calling an MVC action method that returns a partial view. This will call the show action on the foo controller every 5 seconds and update the containerToUpdate (presumably a DIV), with the html returned.
setInterval(
function() {
$.get( '<%= Url.Action( "show", "foo", new { id = Model.ID } ) %>',
function(html) {
$('#containerToUpdate').html( html );
});
}, 5000
);
Server side:
[AcceptVerbs( HttpVerbs.Get )]
public ActionResult Show( int id )
{
var model = ...
if (this.Request.IsAjaxRequest())
{
return PartialView( model );
}
else
{
return View( model );
}
}
The full view (for non-AJAX) may not be necessary -- you may want to just display an error if the user shouldn't be accessing this except through AJAX. If you do support both, just render the partial inside the full view where it's needed so that you reuse the partial view code.

Related

How to do MVC form with very simple lookup?

We have a very simple MVC form with a dropdownlist which gets the user's selected city.
We have a list of cities and we know the average temperature (say) for each city.
Almost as a decoration (it's not a core function) for the form it would be nice to show the temperature for the selected city as the user changes it. Something like this:
This has to happen client side, I guess. Or is it AJAX?
At the moment our form is mostly out-of-the-box MVC4 EF auto built with scaffolding.
We populate the dropdownlist like so:
In the Controller:
ViewData("Cities") = GetCitySelectList()
and in the View:
#Html.DropDownListFor(Function(model) model.City, TryCast(ViewData("Cities"), SelectList))
... so pretty simple stuff.
There are plenty of tutorials for doing cascading dropdowns which are probably overkill for what we're trying to do here. Also if you google "javascript lookup mvc form" or similar a lot of the results tie you to using a framework (knockout? barebone?) which, again, I'm not familiar with and I don't know if I need for such a simple task.
In fact we're so geared to keeping it simple, and our city list is so short, it's almost worth doing it as a giant if then else in javascript (but, I know, yuk).
What's the simplest way to do this?
You can do it as follows:
Make an Ajax call on change on dropdown and then place the result in the corresponding div.
Html for result:
Temperature:<div id="temp"></div>
Ajax call :
$("#dropdownId").change(function () {
$.ajax({
type: "GET",
url: "Home/GetTemperature", // your url
contentType: "application/json; charset=utf-8",
data : {City : " + $(this).val() +"}
dataType: "json",
success: function (result) {
$("#temp").html(result); // place result in div
},
error: function () {
alert("Error.");
}
});
});
Your Action (C#):
[HttpGet]
public JsonResult GetTemperature(string City)
{
int temp = 30; // Get temp from your db..
return Json(temp,JsonRequestBehavior.AllowGet);
}
Your Action (VB):
<HttpGet>
Public Function GetTemperature(City As String) As JsonResult
Dim temp As integer = 30
Return Json(temp, JsonRequestBehavior.AllowGet)
End Function
You should use AJAX call to the server for the temperature. That's probably the "cleanest" way to achieve what you would like to have on your form.
Option 1: Using jQuery and make ajax call to fetch a temprature for the cityId passed and set the html of the temprature div or span container
Option 2: Eager Load on page as Javascript object
You could have eager load the cities and temprature into the JSON object and store it.
Here is the controller action code using JSON.Net for json serialization
public ActionResult myAction()
{
MyViewModel model=new MyViewModel();
List<City> cities=new List<City>();//fill the city id, temp
MyViewModel.CityJSON=JsonConvert.SerializeObject(List<City>);
return View(model)
}
View
#model MyViewModel
// other controls
#Html.HiddenFor(m=>m.CityJSON, new{#id='hdn-city-json'})
JavaScript
var cityList=JSON.parse($('#hdn-city-json')); // returns array of city obj
//do your stuff
If you are trying to avoid unneccesary requests to server, yes, you could eager load the whole collection. You can keep the data in a hidden <ul/> tag that you build on your View. Then, you can use jQuery to fire when the dropdown selection changes. But instead of making an AJAX call, you can lookup the temperature in the list instead and set the content of the target div to the return value of the lookup function.

Use jQuery to .post() to ASP MVC controller method w/Razor

How would you use jQuery to post to a different controller using Razor syntax? Below is the code I'm attempting to use. Each of the alerts pop up the exact information I am expecting except for the one containing the #Url.Action. This gives me a URL that just contains the Controller and method (i.e. /Agent/Details). The sNumber is completely missing.
Oddly enough, this code is still posting to the controller properly, with the correct sNumber parameter. However, once the controller goes through the process of grabbing the agent from the database and attempting to render the view, nothing happens. The user stays on the same page.
Here is the jQuery
alert("input: " + item + ", map: " + map[item].sNumber);
var sNumber = map[item].sNumber;
alert("variable: " + sNumber);
alert('#Url.Action("Details","Agent")', { id: sNumber });
$.post('#Url.Action("Details","Agent")', { id: sNumber });
There is a ton of code in controller, so I'll spare you by not posting it. However, this is the final line
return View(bigAgent);
The controller uses the sNumber input parameter to grab the record from our database and pass that agent's info to the Details view. I've checked the contents of the bigAgent object using both the jQuery search and our regular search (which redirects properly), and they are one and the same. For whatever reason, you are just not directed to the Details page when using the jQuery search.
It's not odd that it's posting correctly. You are using a POST request afterall, so the sNumber parameter doesn't belong in the URL as it would with a GET request (e.g. /Agent/Details/3).
You're not being redirected because when you use jQuery AJAX methods, they happen asynchronously. You need to handle the redirect yourself in the success callback of the $.post() function.
$.post('url', { data }, function(data) {
// callback
});
It sort of seems like you shouldn't be using AJAX at all and should be performing a regular form submission so you can handle the redirect in your controller.

Pass javascript parameter to partial view in asp.net mvc

lets say I want to a partial view like the following sample
#Html.RenderAction("ListDocuments", "MultiFileAttachments", new { id = jsparameter });
in the jsparameter I want to pass as a parameter that is the result of a javascript function. Maybe this is not logical because javascript runs on the client, but how can I achieve a similar functionality ? thank you in advance
If you need to call a part of a page based on some actions or values determined by actions on the client side, then you should think to use JavaScript (preferably jQuery) and Ajax.
Through jQuery-Ajax, you could easily call a Partial view through the Contoler and since it's a regular HTTP request, you would be able to pass all the parameters you need.
Using code as :
#Html.RenderAction("ListDocuments", "MultiFileAttachments", new { id = jsparameter });
is not possible since it is rendered by the server before it's sent to the client browser.

Assign values to ViewData from client using MVC

I inherited an MVC app and am a true novice at it coming from an ASP.NET environment. My problem is I can't manage to move variable data between my partial views and controllers. In ASP.NET this was pretty straight forward, not the case in MVC. So the following code fires when a Tab is selected from the client but I need to capture the selectedTabIndex value from the client and pass it to the controller.
function onTabSelect(e) {
var selectedTabIndex = 0;
selectedTabIndex = $(e.item).index();
alert(selectedTabIndex);
}
I considered using the ViewData object but there doesn't appear to be a way to make perform this task of assignment from within the function. So the following code would seem to be a ridiculous task and it fails anyway. (Remember, I am an extreme novice at this)
function onTabSelect(e) {
var selectedTabIndex = 0;
<% =ViewData["selectedTabIndex"]%> = selectedTabIndex;
}
I also considered using cookies but that doesn't seem to be a practical method either. In ASP.NET I could access the client controls using the .find method but this is a steep learning curve for me.
What are my alternatives?
If different tabs can be selected by the user between Save operations, you might need to consider binding some kind of click function (using jQuery) to set the selectedTabIndex javascript variable. Alternatively, you could set a hidden input's value to the selected tab index.
In either case, if you need the value in your controller (to set ViewData, ViewBag, some model data, etc) when a Save operation is submitted, you could submit the data via $.ajax and return some JSON from your controller
$('#SaveButton').click(function() {
$.ajax({
url: '/Controller/Save',
type: 'POST',
// you might need to serialize additional data you want to save here
// but you could create any JSON object before calling $.ajax
data: {"selectedTabIndex": selectedTabIndex}, // data to POST
dataType: 'json', // this indicates the type of data returned from controller
success: function(data) {
// you didn't really describe how to programatically set a tab,
// so "setToTab" is a guess
$('#tabID').setToTab(data.selectedTabIndex);
}
});
}
And your controller might look something like
public ActionResult Save(int selectedTabIndex)
{
// again, you might need different parameters to complete your Save
return JsonResult(new { selectedTabIndex: selectedTabIndex });
}
Data is sent to a controller via a HTTP POST. Create a hidden input <input type="hidden" name="selectedTabIndex"/> and set the value with javascript prior to POST. The controller can extract this value from the Form parameters, or it can be autopopulated in the Action method if the method contains a parameter matching the input name.
This is a non-ajax alternative to the answer provided by David.

ASP MVC + AJAX, trying to Update a div asynchronously

I'm new to Asp MVC, and I'm trying to accomplish a little async update (I'm using MVC3 RC2, with Razor, but I can manage with ASPX solutions too).
I have a Master page, which renders a shopping cart box on every page by calling Html.RenderAction("Cart","Shop"). The Cart action of the ShopController calls the database, etc, and outputs the results. This works.
First problem: if I put an ActionLink in this partial view (like Html.ActionLink("Remove")), then even if I call PartialView() from the Remove action, it renders only the shopping cart, and nothing else (in essence, my page disappears).
Second problem: There is a div called "cartContent" inside this partial view. I want to be able to put a link ANYWHERE (not just on the Master page or in the partial view), which when pressed calls a controller Action, and then updates ONLY the cartContent div based on the results. I've tried Ajax.ActionLink but it does the same as Html.ActionLink, even though I imported the Microsoft.MvcAjax js libs.
Also, if I solve the first problem, I want that to be async as well.
What solution do I use? I've tried setting UpdateTargetID to "cartContent", I've tried wrapping the cartContent into an Ajax.BeginForm, nothing. Do I HAVE to use jQuery (which I know nothing of)? Do I serialize some response to JSON, and update the div manually in Javascript? (I'm not really good at JS, I'm coming from the C# side of things)
You put a link wherever you want:
#Html.ActionLink("remove item", "remove", "somecontroller",
new { id = Model.Id }, new { #class = "remove" })
And then in a separate javascript file:
$(function() {
$('.remove').click(function() {
// when the link is clicked
// perform an ajax request:
$.ajax({
url: this.href,
type: 'delete',
success: function(result) {
// when the AJAX call succeed do something with the result
// for example if the controller action returned a partial
// then you could show this partial in some div
$('#someDivId').html(result);
}
});
// don't forget to cancel the default action by returning false
return false;
});
});
Remark: if the div you are updating contains also the link then you might need to use the .live() function or the click event handler will not work the second time because the DOM will be modified:
$('.remove').live('click', function() {
...
});

Resources