File response in asp.net core API - asp.net-core

I have searched many times for my problem but I couldn't find any solution.
the problem which faced is I wrote method yesterday in asp.net core API which is return file response as streaming video when I tried to test on my local machine it's working very well, but when uploading it to my VPS server I got the 500 internal server error so please what is the problem.
the following my code which I used:
[HttpPost("youtube")]
public async Task<IActionResult> GetYoutubeVideoURL([FromBody] string url)
{
if (string.IsNullOrEmpty(url))
{
return Ok(new { Error = "Please provide your url for fetch video." });
}
var id = YoutubeClient.ParseVideoId(url);
if (id == null)
{
return Ok(new { Error = "Video id is not available, try again later." });
}
var client = new YoutubeClient(); //This should be initialized in YoutubeController constructor.
var mediaInfoSet = await client.GetVideoMediaStreamInfosAsync(id);
var mediaStreamInfo = mediaInfoSet.Audio.WithHighestBitrate();
var mimeType = $"audio/{mediaStreamInfo.Container.GetFileExtension()}";
var fileName = $"{id}.{mediaStreamInfo.Container.GetFileExtension()}";
return File(await client.GetMediaStreamAsync(mediaStreamInfo), mimeType, fileName, true);
}

Related

Error in ASP.NET Core MVC and Web API project

I have an ASP.NET Core MVC and also Web API project.
This error occurs when I try to send project information to the API (of course API works fine and I do not think there is a problem):
UnsupportedMediaTypeException: No MediaTypeFormatter is available to read a "TokenModel" object of "text / plain" media content.
My code is:
public class TokenModel
{
public string Token { get; set; }
}
and in AuthController I have:
var _Client = _httpClientFactory.CreateClient("MyApiClient");
var jsonBody = JsonConvert.SerializeObject(login);
var content = new StringContent(jsonBody, Encoding.UTF8, "application/json");
var response = _Client.PostAsync("/Api/Authentication", content).Result;
if (response.IsSuccessStatusCode)
{
var token = response.Content.ReadAsAsync<TokenModel>().Result;
}
The error occurs on this line:
var token = response.Content.ReadAsAsync<TokenModel>().Result;
HomeController:
public IActionResult Index()
{
var token = User.FindFirst("AccessToken").Value;
return View(_user.GetAllUsers(token));
}
UserRepository:
public List<UserViewModel> GetAllUsers(string token)
{
_client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var res = _client.GetStringAsync(UrlMyApi).Result;
List<UserViewModel> users = JsonConvert.DeserializeObject<List<UserViewModel>>(res);
return users;
}
Your API is returning content-type of text/plain and none of the default media type formatters(MediaTypeFormatter) which ReadAsAsync<string>() will try to use support parsing it as is. They work with JSON/XML. You can go a couple of ways but maybe the easiest is to read the content as string and deserialize it after:
var tokenJSON = response.Content.ReadAsStringAsync().Result;
var token = JsonConvert.DeserializeObject<TokenModel>(tokenJSON);
Also, as you're using the Async methods, you should be returning Task from your actions and await the result instead of using .Result as you're just creating overhead currently.
var tokenJSON = await response.Content.ReadAsStringAsync();
var token = JsonConvert.DeserializeObject<TokenModel>(tokenJSON);

ASP.NET Core 3.1 - PostAsync/PostAsJsonAsync method in Integration Test always returns Bad Request

This is my register method inside the AuthController.
[HttpPost(ApiRoutes.Auth.Register)]
public async Task<IActionResult> Register(UserRegistrationRequest request)
{
var authResponse = await _authService.RegisterAsync(request.Email, request.Password);
if (!authResponse.Success)
{
return BadRequest(new AuthFailedResponse
{
Errors = authResponse.Errors
});
}
return Ok(new AuthSuccessResponse
{
Token = authResponse.Token,
RefreshToken = authResponse.RefreshToken
});
}
I'm trying to call this method by using TestClient.PostAsync() method, unfortunately it always returns Bad Request. I've already tried calling the TestClient.PostAsJsonAsync(ApiRoutes.Auth.Register, user) method by importing Microsoft.AspNet.WebApi.Client package, the result is the same.
var user = new UserRegistrationRequest
{
Email = "user1#testtest.com",
Password = "P#ssw0rd1!!!!!"
};
var response = await TestClient.PostAsync(
ApiRoutes.Auth.Register,
new StringContent(JsonConvert.SerializeObject(user), Encoding.UTF8)
{
Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
});
You are missing the FromBody attribute from you action parameter. When you are sending json data to a controller that will be part of the request body. You can tell to the controller how to bind the incoming data, in your case from the body. So you code should look like:
public async Task<IActionResult> Register([FromBody]UserRegistrationRequest request)
{
…
}
You could read more about bindings in the official documentation.

PostAsync request with Array parameter on MVC Web API

I have Xamarin application that has POST request with array list of parameter and on my MVC WEB API we used code first Entity framework. Both was separated project solutions (.sln).
On my Xamarin project, I have PostAsync request which supplies List of array values.
using (var client = new HttpClient())
{
Parameter = string.Format("type={0}&param={1}",type, param[]);
var data = JsonConvert.SerializeObject(parameters);
var content = new StringContent(data, Encoding.UTF8, "application/json");
using (var response = await client.PostAsync(url, content))
{
using (var responseContent = response.Content)
{
result = await responseContent.ReadAsStringAsync();
}
}
}
Then In my Web API controller I have same parameter with my client side also.
[System.Web.Http.AcceptVerbs("GET", "POST")]
[System.Web.Http.HttpPost]
[Route("type={type}&param={param}")]
public BasicResponse applog([FromUri] ProfilingType type , List<string> param)
{
if (ModelState.IsValid == false)
{
throw new ModelValidationException("Model state is invalid.");
}
try
{
if(type == ProfilingType.Login)
{
var command = new SendDataProfilingCommand(param);
CommandHandler.Execute(command);
}
else
{
var command = new UpdateDataProfilingCommand(type,param);
CommandHandler.Execute(command);
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
return new BasicResponse
{
Status = true,
Message = Ok().ToString()
};
}
Since I'm not with the API, I want to test it first on Postman or even in the URL. but my problem was when i Try to test it using this url below
http://localhost:59828/api/users/applog?type=1&param=[1,Caloocan,Metro Manila,Philippines,0,0]
I received this message : No HTTP resource was found that matches the request URI ......
My Question is, How can I test my Web API with List Parameter on URL or in the Postman ? and What Format I can use when sending a post request into my Xamarin PostAsync request?
You don't need to send as Content.
using (var client = new HttpClient())
{
Parameter = string.Format("type={0}&param={1}",type, param[]);
url = url + "?" + Parameter;
using (var response = await client.PostAsync(url))
{
using (var responseContent = response.Content)
{
result = await responseContent.ReadAsStringAsync();
}
}
}

How to implement the await keyword?

I have written a code to get the projects from the TFS 2013 server using the tfs web api. As the methord is taking too long to execute i.e like 1.5 minutes, so i wanted to make this methord as async. So i added the async and task in the return type. When i see in visual studio is shows a message that the methord does not have await keyword. where should i add the await keyword. I am very new to async programming.
public override async Task<List<Project>> GetProjects()
{
List<Project> retunResult = new List<Project>();
using (var http = new HttpClient(GetHttpHandler()))
{
var response = http.GetAsync(_baseUrl + "_apis/projectCollections?" + tfsWebApiVersionSring).Result;
if (response.IsSuccessStatusCode)
{
response.EnsureSuccessStatusCode();
TFS2013TeamProjectCollection.Rootobject obj = JsonConvert.DeserializeObject<TFS2013TeamProjectCollection.Rootobject>(response.Content.ReadAsStringAsync().Result);
if (obj != null)
{
foreach (TFS2013TeamProjectCollection.Value projColl in obj.value)
{
if (projColl.state == "Started")
{
var responseProj = http.GetAsync(_baseUrl + projColl.name + "/_apis/projects?" + tfsWebApiVersionSring).Result;
if (responseProj.IsSuccessStatusCode)
{
responseProj.EnsureSuccessStatusCode();
TFS2013TeamProject.Rootobject obj1 = JsonConvert.DeserializeObject<TFS2013TeamProject.Rootobject>(responseProj.Content.ReadAsStringAsync().Result);
if (obj1 != null)
{
Project p;
foreach (TFS2013TeamProject.Value TeamProj in obj1.value)
{
p = new Project();
p.collectionName = TeamProj.collection.name;
p.description = TeamProj.description;
p.id = TeamProj.id;
p.name = TeamProj.name;
p.collectionName = TeamProj.collection.name;
p.url = TeamProj.url;
retunResult.Add(p);
}
}
}
}
}
return retunResult;
}
}
}
return null;
}
You could refer to this code snippet about using TFS REST API to get something in async way.
public static async void RESTAPIMethod()
{
HttpClientHandler authtHandler = new HttpClientHandler()
{
Credentials = CredentialCache.DefaultNetworkCredentials
};
using (HttpClient client = new HttpClient(authtHandler))
{
client.DefaultRequestHeaders.Accept.Add(
new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
using (HttpResponseMessage response = client.GetAsync(
"Put the REST API URL here").Result)
{
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
}
}
}
Another method about using TFS REST API:
You could also install this Nuget package for your project. Then using these assemblies in this package to run a REST API with C#. This is different with the method above, it's much more convenient. Here is an example about get a build information using Microsoft.TeamFoundation.Build.WebApi assembly in Async method.
Example:
What object returns from TFS2015 RestAPI
You shouldn't use Result at all. Every place in your code where you have:
var resp = http.GetAsync(url).Result;
you should have:
var resp = await http.GetAsync(url);

Cannot use SendTweetWithMediaOptions in windows phone

I am using TweetSharp in a Windows Phone project and no matter what I do, I can't post a tweet with media.
I am getting the exception 195: Missing or invalid parameter.
I read that usually this can be a cause of invalid data, like the stream that I provide is invalid.
I have tried other way but nothing works , I get the same exception ...
The sharing code, simplified is like this:
MediaLibrary library = new MediaLibrary();
var picture = library.Pictures[0];
var options = new SendTweetWithMediaOptions
{
Images = new Dictionary<string, Stream> { { picture.Name, picture.GetImage() } },
Status = TweetTextBox.Text,
};
AutentificateTwitterService().SendTweetWithMedia(options, (status, response) =>
_dispatcher.BeginInvoke(() =>
{
DonePosting();
if (response.StatusCode == HttpStatusCode.OK)
{
_lastPostId = status.Id;
}
else
{
MessageBox.Show(String.Format(
"There was an error sending image to Twitter{0}{1}",
Environment.NewLine,
response.Error));
}
}));
I tried sharing with linqtotwitter and worked but TweetSharp is more appropriate for my project.
Finally after some time I've found the problem to this and I am sure to other more WP and SendTweetWithMediaOptions related problems.
The thing is that if you dig into SendTweetWithMedia the way it is now you will get to TwitterService.cs where WithHammock will be called, is just the images are not passed as parrameters, so they get lost right there :)
I did fix this passing the parameters and adding
private void WithHammock<T>(WebMethod method, Action<T, TwitterResponse> action, string path, IDictionary<string, Stream> files, params object[] segments) where T : class
{
var url = ResolveUrlSegments(path, segments.ToList());
var request = PrepareHammockQuery(url);
request.Method = method;
request.QueryHandling = QueryHandling.AppendToParameters;
foreach (var file in files)
{
request.AddFile("media[]", file.Key, file.Value);
}
WithHammockImpl(request, action);
}
I will try and see if I can Pull this so that everyone else can have this fix.
Hope this helps.