how to get images from ApiControler - asp.net-mvc

I have created a model and a view and displayed some needed data from the model using simple GameController.
Now i am searching(didn't found anything usefull) on how to get 9 images and show them in the page using ApiController(9 images that can be used for a puzzle) and modifying the page that GameController has returned, without loading the whole page.
The idea is that i want to call the method from ApiController 9 times and to show the images in a grid/table or somewhere.
I can use an example on how to do this since i didn't found something relevant on google and someone with knowledge can do it very fast.
If something is unclear, just ask.
Thanks,
Gabriel Sas

There is an example here:
public HttpResponseMessage GetImage()
{
HttpResponseMessage response = new HttpResponseMessage();
response.Content = new StreamContent(new FileStream(#"path to image")); // this file stream will be closed by lower layers of web api for you once the response is completed.
response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
return response;
}

Related

Read API Response Messages

I have Developed ASP.net Core Web API & Web APP Which are in the same solution but different projects.
in the API I have some validations/checking as you may call.
e.g: if user email already exists, the API returns 'Email alreday in use' like this
bool EmailExists = dbContext.Users.Any(u => u.Email == user.Email);
if (EmailExists)
{
return new JsonResult("Email Address already taken!, Try a differen Email");
}
and so on. in some cases I may need to check multiple columns one a time, (eg: UserName, Email, TellNum)
This is an example of calling the API in the MVC
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseAPIUrl);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage Res = await client.PostAsJsonAsync("Users", user);
if (Res.IsSuccessStatusCode)
{
//in here I want check the `Res` and if it contains the returned messages, I want to display them by assigning it to `TempData[infoMsg]`
// else some something(register user)
}
// Check the returned JsonResult messages here if statusCode is ultered eg: BadRequest
}
My Question is how can I display these types of response messages in razor view in the MVC(Web App). in PostMan its workin, returning the response messages in body.
I did a lot of research about this but couldn't come to conclusion. I also cantacted some Devs I know(not .NET) and they said use JavaScript to call your API, which means I have to change almost everything I have done so far.
I aslo tried ultereing the statuCode to something like BadRequest in the API(if Email exists) in which case it will be checked outside the if (Res.IsSuccessStatusCode) of the Httpclient.
any help or direction is highly appreciated.
You should return a http error and a body containing some data about it eg field and message to your mvc controller. That could be a 422 error or whatever you like really since it's effectively internal and just coming back to the mvc controller.
The controller can then add any such error to modelstate and you can use the razor model "client" validation mechanism to show the error associated with a field.
This is therefore using the same mechanism used for attribute validation in the controller where you'd do
if (!ModelState.IsValid)
This is air code but will hopefully give you the idea.
[HttpPost]
public ActionResult PostUpdate(User u)
{
// call service and await response
var response = await httpClient.PostAsJsonAsync(posturi, u);
var returnContent = await response.Content.ReadAsAsync<ReturnContent>();
if (response.Result != HttpStatusCode.OK)
{
ModelState.AddModelError(returnContent.FieldName,returnContent.Error);
return Page();
}
// etc
You will want a more sophisticated checking on errors of course and check you get the body you're expecting.
Maybe you just hard code the field and error message if there's only one possibility. Maybe work with an array of fields and errors if there could be numerous validation fails.

Post Data to next Page in Custom Save Action Web Form For Marketer Sitecore 8

After saving data in WFFM Custom save Action,I want to redirect Success Page with some large amount of data
I am trying below line of code .
I Can use Cookies ,session or Query String and Response.Redirect(baseUrl)but i want to Cookies ,session or Query String .
class SaveAction : WffmSaveAction
{
public override void Execute(ID formId, AdaptedResultList adaptedFields, ActionCallContext actionCallContext, params object[] data)
{
//Save Data in Service ,, Redirect to success page with below code with some data like ID
string baseUrl = HttpContext.Current.Request.Url.Scheme + "://" + HttpContext.Current.Request.Url.Authority +
HttpContext.Current.Request.ApplicationPath.TrimEnd('/') + "/success-page";
HttpContext.Current.Response.Clear(); //
StringBuilder sb = new StringBuilder();
sb.Append("<html>");
sb.AppendFormat(#"<body onload='document.forms[""form""].submit()'>");
sb.AppendFormat("<form name='form' action='{0}' method='post'>", baseUrl);
sb.AppendFormat("<input type='hidden' name='id' value='{0}'>", "123456");
// Other params go here
sb.Append("</form>");
sb.Append("</body>");
sb.Append("</html>");
HttpContext.Current.Response.Write(sb.ToString());
HttpContext.Current.Response.End();
// HttpContext.Current.Response.Redirect(baseUrl);
}
}
Above code reload the same page with no body in Html.
Am i missing something in given code ?
The answer might depend on whether you have an mvc form or not.
In case of mvc forms, you might want to read this: http://ggullentops.blogspot.be/2016/07/sitecore-wffm-act-on-success.html. It describes hooking into the success pipeline <wffm.success> and passing data towards the success page (how exactly - querystring, session, .. is up to you(r code)). Fairly easy once you know the correct pipeline.
There is also a great post here describing what you are trying to do - i.e. saving the data for later use in the saveaction. It's too much code to copy here but it comes down to saving the data (in session) during the save action and creating a rendering (to read and handle the data again) that you will place on the success page.
Creating a rendering to place on your success page is something you will have to do anyway.. Don't try to redirect yourself, Sitecore does that for you.

Multi Post for Action with return File in ASP.NET MVC

Assume this code in One of my Actions
[HttpPost]
public ActionResult Generate (Params){
....
InsertOneRawToDB();
return RedirectToAction("Index", new { info = info });
}
So every thing is OK yet but when I change return to:
InsertOneRawToDB();
byte[] myfile = GenerateAZipFile();
return File( myfile , "application/zip" , "MyFileName");
In this case I see a weird behavior: before return, One raw inserted to DB, and after return another raw inserted, it seems the InsertOneRawToDB called again.
Does any one know about this? what happening here?
PS: I use Visual Studio 2012 RTM + ASP.NET MVC4
PS: OK I Use IDM (Internet Download Manager) to download zip file and that cause MultiPost on this Action So How can I handle this?
Based on your conclusion that the problem is related to using a download manager... That's what download mangers do. They create multiple connections to the file.
One thing you could do is store a session variable that says "Already started downloading", and then only insert the record the first time.
however if the user legitimately downloaded the file multiple times then you would only get one record.
Another option would be to examine the Http headers and look for the "Range" header, which is what is used to download a file in multiple pieces (or resume a file). You would then have to take the Range parameters and only return the portion of the file requested.
Here's an example of how to do a Ranged download: http://tpeczek.com/2011/10/range-requests-in-aspnet-mvc.html
I'm actually quite surprised that this hasn't come up before... I guess most people don't do database actions in a download action or notice it.
You can redirect to new action and in this new action return file.
[HttpPost]
public ActionResult Generate (Params){
....
InsertOneRawToDB();
return RedirectToAction("GetFile"};
}
[HttpGet]
public ActionResult GetFile
{
byte[] myfile = GenerateAZipFile();
return File(myfile, "application/zip", "filename.ext");
}

Render view to string followed by redirect results in exception

So here's the issue: I'm building e-mails to be sent by my application by rendering full view pages to strings and sending them. This works without any problem so long as I'm not redirecting to another URL on the site afterwards. Whenever I try, I get "System.Web.HttpException: Cannot redirect after HTTP headers have been sent."
I believe the problem comes from the fact I'm reusing the context from the controller action where the call for creating the e-mail comes from. More specifically, the HttpResponse from the context. Unfortunately, I can't create a new HttpResponse that makes use of HttpWriter because the constructor of that class is unreachable, and using any other class derived from TextWriter causes response.Flush() to throw an exception, itself.
Does anyone have a solution for this?
public static string RenderViewToString(
ControllerContext controllerContext,
string viewPath,
string masterPath,
ViewDataDictionary viewData,
TempDataDictionary tempData)
{
Stream filter = null;
ViewPage viewPage = new ViewPage();
//Right, create our view
viewPage.ViewContext = new ViewContext(controllerContext,
new WebFormView(viewPath, masterPath), viewData, tempData);
//Get the response context, flush it and get the response filter.
var response = viewPage.ViewContext.HttpContext.Response;
//var response = new HttpResponseWrapper(new HttpResponse
// (**TextWriter Goes Here**));
response.Flush();
var oldFilter = response.Filter;
try
{
//Put a new filter into the response
filter = new MemoryStream();
response.Filter = filter;
//Now render the view into the memorystream and flush the response
viewPage.ViewContext.View.Render(viewPage.ViewContext,
viewPage.ViewContext.HttpContext.Response.Output);
response.Flush();
//Now read the rendered view.
filter.Position = 0;
var reader = new StreamReader(filter, response.ContentEncoding);
return reader.ReadToEnd();
}
finally
{
//Clean up.
if (filter != null)
filter.Dispose();
//Now replace the response filter
response.Filter = oldFilter;
}
}
You'd have to initiate a new request.
Bit, do you really want to send emails synchronously this way? If the mail server is down, the user could be waiting a good while.
I always put emails in an offline queue and have a service mail them. You might consider using the Spark template engine for this.
One other approach is to not redirect but write out a page with a meta redirect tag
Here is an alternative method for rendering a view to a string that never results in data being output to the response (therefore it should avoid your problem): http://craftycodeblog.com/2010/05/15/asp-net-mvc-render-partial-view-to-string/
To render a regular view instead of a partial view, you'll need to change "ViewEngines.Engines.FindPartialView" to "ViewEngines.Engines.FindView".
Have a look at the MVC Contrib EmailTemplateService which does exactly what you are after.
http://mvccontrib.googlecode.com/svn/trunk/src/MVCContrib/Services/EmailTemplateService.cs
Sorry Chris, not quite sure what I was thinking but I obviously didn't read the question. While I cannot give you a way around this, I can tell you why you are getting the error - HttpResponse.Flush() sends the headers before flushing the content to your filter. This sets a flag inside the response so that when you try to redirect you get the exception.
Using reflector to look at the code inside Flush, I can't see any clean way for you to get around this without a lot of reflection and other nastiness.

HOW? Controller return nothing/current view

SHORT:
How do I make a controller return the current view or just simply do nothing?
LONG:
I have a partial view where i've created an imageslider.
It contains a link which sends a request to a controller to get the next image (using ajax).
The controller fetches the next image, stores it in ViewData and sends back a partial view (the one above).
Now, what I do today is that when the controller reaches the last image it re-return the very same image (by refetching it), but still creates a new view, that is, the client/browser re-parses the "same" data.
This seems somewhat non-optimal.
What I'd like to do is that when controller reaches the last image it should simply do nothing.
If I return null then the view is updated with empty contents.
I want the view/client/browser to retain whatever it has and the controller to simply do nothing.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult GetNextImage(...)
{
if(Request.IsAjaxRequest())
{
if(CURRENT_IMAGE != LAST_IMAGE)
{
Image image = GetNextImage(...);
var partialViewResult = new PartialViewResult();
partialViewResult.ViewName = "ImageSlide";
partialViewResult.ViewData.Model = image;
return partialViewResult;
}
else
{
// DO NOTHING, HOW?
}
}
return RedirectToAction("Error", "Home");
}
You can return an EmptyResult if you want it to do nothing...
return new EmptyResult();
If you're using the AjaxHelper you can avoid the update by supplying an unsuccessful status code (e.g. 404 or whatever is most appropriate), that'll stop it replacing your div as the javascript in MicrosoftMvcAjax.js explicitly checks for a successful response before updating any elements:-
this.ControllerContext.HttpContext.Response.StatusCode = 404;
return new EmptyResult();
Ultimately the best way to avoid it is to design the partial view so it avoids the problem in the first place (like you mention yourself).
I ran into this problem today. I wanted to find a solution for how to deal with double-clicks on the client side trying to reenter the controller action on the server side while it was still processing. If a user entered that action, I wanted it to just ignore the request and do nothing on the browser side.
Solution looks like this:
public async Task<ActionResult> MyAction()
{
if(!CanEnterAction(nameof(MyAction))) return new HttpStatusCodeResult(204);
try
{
// Do long running stuff
return ValidActionResult();
}
finally
{
ExitedAction(nameof(MyAction));
}
}
Returning a status code of 204 basically does nothing to the page displayed in the browser. The actual result eventually makes it back to the browser when the action is complete.
This question is old, but I wasn't able to find an answer anywhere on StackOverflow. I figured it had to be possible since a FileResult doesn't really affect the current page, either, other than saving a file.
I would use
return new HttpStatusCodeResult(204);
this way you would stay on the same page and there is no post back.
Here is the defination
The HTTP 204 No Content success status response code indicates that the request has succeeded, but that the client doesn't need to go away from its current page
Assuming that you are using MicrosoftMvcAjax, you could send back a JavascriptResult that alerts the user that they have reached the end of the slider. If the response is javascript rather than content, the MicrosoftMvcAjax handler executes it instead of replacing the DOM contents.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult GetNextImage(...)
{
if(Request.IsAjaxRequest())
{
if(CURRENT_IMAGE != LAST_IMAGE)
{
Image image = GetNextImage(...);
var partialViewResult = new PartialViewResult();
partialViewResult.ViewName = "ImageSlide";
partialViewResult.ViewData.Model = image;
return partialViewResult;
}
else
{
return JavaScript( "alert('No more images');" );
}
}
return RedirectToAction("Error", "Home");
}
Of course, you'd probably want to be more creative and use the jQuery dialog plugin or something rather than an alert.
Ok, I've got it.
Not a solution to my question but still solves the problem.
I'll simply not show the "Next" link when the view shows the last image.
Can't believe I didn't think of it earlier...
Thanks for your efforts guys

Resources