Does (HTML.Action) send another request to the server other than the main request? - asp.net-mvc

I am wondering if (HTML.Action) send another request to the server other than the main request.
For example, when Razor renders the below view. Does it send a new request to the server to execute the action (SearchResults)?
#Html.Action("SearchResults", "MySearch",
new { query = new QueryParameters(Request.QueryString["search"]) })

You can see whether it send another request or not using network tab under developer tools.Html.Action is just a helper method like any other ,purpose of it is rendering view via calling another action , all it happens when razor renders page.So complete html send to browser in a single request so main request.

When you are rendering actions/partials in a View there is only one request.
If you want to test this you can debug it in your global.asax with this method:
protected void Application_BeginRequest(object sender, EventArgs e)
{
}

Related

how do i call webservice from MVC3 Razor Controller?

In my project I need to call a web service from a controller. I have already done the following, and it works.
Add the web reference for the web service to the project.
Call the service as follows:
Service Wservice=new Service();
Wservice.loginCompleted+=new Wservice_login_Completed;
WService.login_Async("username","Password");
Note: Whenever i call this service it throws an error that is
"An asynchronous operation cannot be started at this time.
Asynchronous operations may only be started within an asynchronous handler
or module or during certain events in the Page lifecycle. If this
exception occurred while executing a Page, ensure that the Page is marked
<%# Page Async="true" %>."
To overcome this issue I use
[Httppost]
public ActionResult login(logmodel model)
{
Task.Factory.StartNew(() =>
{
Wservice.loginCompleted+=new Wservice_login_Completed;
WService.login_Async("username","Password");
});
if(finalresult==true)
{
*** return View();
}
}
void Wservice_login_completed()
{
Here i got the output.
}
But the calling of Wservice_login_completed() function was after the View*** was returned,, so I'm not getting the result. How do I achieve "calling webservice from Controller".. Any ideas?
Finally i called the webservice from MVC Controller Successfully.
Note: Add ServiceReference instead of WebReference and avoid
"Task.Factory.StartNew(()=>);" Process.
[Httppost]
public ActionResult login(logmodel model)
{
Wservice.ServiceSoapClient _host = new Wservice.ServiceSoapClient("ServiceSoap");
var result_out = _host.login(uname, pwd, "test1", "test2", "test3", "test4");
}
Here "ServiceSoap" is an endpoint for our service.. you may got the endpoint to be presented in app.confiq or web.config files.
Happy Coding...!
get the following NuGet:
microsoft http client
(id = Microsoft.Net.Http)
Create a Web API Controller (webapi_Controller_Name)
Your Post function should be similar to the following function
Put this function in your Web Api Controller
[HttpPost]
public void PostForm(objUser ws_Obj)
{
// put you code here
}
Call your Web Service from you regular Controller as follows.
This is an Async call and will Web Service will return immediately.
//call the web service, Asynch
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("52323/");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.PostAsJsonAsync("//52323/api/webapi_Controller_Name/PostForm", objContact);
First, create a service reference by right clicking on the project name in the solution explorer, then hover over the "Add" option and click on "Service Reference..."
Second, paste your web service address in the "Address" field of the "Add Service Reference" page, be sure to add "?wsdl" to the end of your web service address or it won't work, and then press "Go". You will see the web service appear in the "Services" area. Click on the service to see the available services which will appear in the "Operations" section. Rename the service if you want, then press OK to create the service.
Finally, put the following code in your MVC Controller. Place the code in a Get or Post controller, it doesn't matter.
// Declare the Request object.
ServiceReference1.GetSurveyRequest myGSRq = new ServiceReference1.GetSurveyRequest();
// You can set the webservice parameters here like...
myGSRq.Address = getUserData[0].address;
myGSRq.City = getUserData[0].city;
myGSRq.State = getUserData[0].state;
// Now declare the Response object.
ServiceReference1.GetSurveyResponse myGSR = new ServiceReference1.GetSurveyResponse();
//And then use the following to process the request and response.
ServiceReference1.EMPortTypeClient emptc = new ServiceReference1.EMPortTypeClient();
myGSR = emptc.GetSurvey(myGSRq);
// In this example the response Object comes back with a URL used to redirect the user
//after the webservice has been processed.
if (myGSR.Url != null)
Response.Redirect(myGSR.Url.ToString());
else
Response.Write("Error");
return null;
Pretty simple, hope this helps!
If you are creating a new service and have the option of using a webservice or a Web API, I suggest using Web API.
Build RESTful API's with ASP.NET Web API

ASP.NET MVC 4: Handle exception caused by JsonValueProvider

I have an action that is called using requests with application/jsonin the Content-type header. These requests will automatically create a JsonValueProvider that tries to deserialize the request's content. When the json is malformed, the value provider will throw an exception leading to the application's error page.
To reproduce this behavior, simply POST invalid json data to an action sending application/json as the Content-type header. This will trigger the exception.
[Edit]
Not much code is needed. Simply create an empty controller method and use a tool like Firefox "Poster" to send an invalid request to the action.
public class HomeController
{
public ActionResult Index()
{
return this.Json(true);
}
}
Then use Poster:
Set Content-type to application/json
Set Request content to {"This is invalid JSON:,}
Send the request
The result will be the full-blown standard ASP.NET HTML error page (either generic or custom, depending on your application).
[/Edit]
Since my action is called by embedded devices, I would like to send short responses, instead of the HTML error page. I would like to be able to create a response with status code 500, Content-type: text/plain, and the exception's message as it's content.
I have already tried a custom model binder and a custom error handler attribute but neither are called since the exception occurs earlier on in the processing pipeline. Is there a way to handle this error?
As a workaround, I have currently disabled the JsonValueProvider for the whole application and load the values from the request body myself. If there is a way to disable the JsonValueProvider on a per action basis, this would also help.
Thanks in advance for any pointers!
You could subscribe to the Application_Error event in your Global.asax and handle the exception as you want:
protected void Application_Error(object sender, EventArgs e)
{
var exception = Server.GetLastError();
Response.TrySkipIisCustomErrors = true;
Response.Clear();
Server.ClearError();
Response.StatusCode = 500;
Response.ContentType = "text/plain";
Response.Write("An error occured while processing your request. Details: " + exception.Message);
}

Long action and waiting for a new view in ASP.NET MVC 3

I'm using ASP.NET MVC3. In the view, I have a link in view that initiates a new request:
#Html.ActionLink ("Link", "LongAction", "Home")
The action "LongAction" takes a long time, and while waiting for the new view I want show an image that simulates loading a whole new view:
public ActionResult LongAction()
{
Threas.Sleep(10000);
return View();
}
You can do something like this:
User Clicks button
Show a loading GIF
POST/GET to a server endpoint
Server endpoint kicks of the long running task.
On the complete event of the ajax request hide the loader.
Notify user
You can look into binding it together with Jquery, or if you want to use something in the mvc framework you can look at the Ajax ActionLink. Either way you can hide/show the loader with javascript.
JQuery Example:
$('#userButton').click(function(){
longRunningTask();
return false;
});
function longRunningTask()
{
$('#loader').show();
$.ajax({
url: 'http://serverendpointaddress.co.uk'
}).done(function(){
//notify the user
}).always(function() {
$('#loader').hide();
});
}

Why is Phase Listener-based JSF redirect not working for AJAX requests when session has timed-out?

I have a JSF Phase Listerner that checks to see if the user is logged in, and if not, redirects them to the login page. This is working fine for non-ajax requests. However, if the user is on a page, in my case, one that has a primefaces data table, and clicks on a button that invokes an ajax request -- but their session has timed out -- the code gets executed that issues the redirect (using ExternalContext#redirect), however the user is not navigated to the login page.
Any idea why this is not working?
Here is my phase listener:
private static final String IS_LOGGED_IN_INDICATOR = "loggedIn";
private static final String LOGIN_PAGE = "/login.jsp";
public PhaseId getPhaseId() {
return PhaseId.RESTORE_VIEW;
}
public void beforePhase(PhaseEvent event) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
HttpSession session = (HttpSession)ec.getSession(false);
if (session==null || session.getAttribute(IS_LOGGED_IN_INDICATOR) == null) {
try {
ec.redirect(LOGIN_PAGE);
}
catch(IOException e) {
// log exception...
}
}
}
public void afterPhase(PhaseEvent event) {
// no-op
}
}
It failed because the ajax context is trying to obtain the render kit from the view root, while there is no view root at all. It has not been restored at that point yet. This resulted in a NullPointerException in PartialViewContext#createPartialResponseWriter(). This exception is in turn not been thrown, but instead been put in an ajax exception queue which is supposed to be handled by a custom ExceptionHandler. You apparently don't have any one. This exception is visible if you create/use such one like the FullAjaxExceptionHandler (see also this blog for more detail).
To fix the particular problem, do the job in afterPhase() instead. The view root is then fully restored and the ajax context can obtain the render kit from it in order to write a specialized XML response which instructs the JSF ajax engine in JavaScript to change the window location. Without ajax, a render kit was not necessary as a redirect is basically just a matter of setting a response header.
Whether the particular NullPointerException is in turn a bug in Mojarra or not is a different question which can better be posted in flavor of an issue report at their own issue tracker.
this is because you have to send a special response in XML for Ajax request in order to do redirect (check this answer) , I have implemented this in a Filter like this..
// Check if it's an Ajax Request
if ("partial/ajax".equals(((HttpServletRequest) request).getHeader("Faces-Request"))) {
//redirect
response.setContentType("text/xml");
response.getWriter()
.append("<?xml version= \"1.0\" encoding=\"UTF-8\"?>")
.printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>",url);
you should port this to your Phase Listener.

Redirect after EndInvoke in ASP.NET MVC

Hi have the following code on my view (JQuery):
$.post('<%=Url.Content("~/Customer/StartLongRunningProcess")%>');
Wich invokes an asynchronous call (C#):
public void StartLongRunningProcess()
{
ProcessTask processTask = new ProcessTask();
processTask.BeginInvoke(new AsyncCallback(EndLongRunningProcess), processTask);
}
Finally, the result of the call:
public void EndLongRunningProcess(IAsyncResult result)
{
ProcessTask processTask = (ProcessTask)result.AsyncState;
string id = processTask.EndInvoke(result);
RedirectToAction("~/SubscriptionList/SubscribedIndex/" + id);
}
The redirect is ignored. Response.Redirect also fails, since the HTTP headers has been already sent. I've tried change the window.location from javascript, this works, but I'm unable to pass the parameter id by ViewData. Any idea to resolve this?
Are you sure the headers have already been sent? I'm not really up on asynchronous controllers, but I would doubt that it would start sending any headers right away. My first thought would be that a redirect response to an ajax call isn't handled by the browser. You will probably need to implement some logic that sends back a result with the URL and have your success delegate in jQuery look for that piece of data and then do the redirect through javascript (i.e. window.location).
HTH

Resources