web api call from code behind - asp.net-mvc

i am very new to mvc web api
I have crated a web api Post method which takes an object type "Bag" and return a HTMLString the code is as shown bellow
public HtmlString PostBag(Bag bagofItem)
{
return Utility.PostBagDiscountedItem(bagofItem);
}
now from my web site i wanted to call the API method PostBag from the controller PostBag()
and i am do not know how to and appreciate if some one can show me how to do this
what i have got in my web application is as bellow.
public class HomeController : Controller
{
private Bag _bag = new Bag();
private string uri = "http://localhost:54460/";
public ActionResult PostBag()
{
// would some one show me how to POST the _bag to API Method PostBag()
return View();
}
public class Bag
{
private static List<Product> _bag { get; set; }
public List<Product> GetBag ()
{
if (_bag == null)
_bag = new List<Product>();
return _bag;
}
}

Try this:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:54460/");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(_bag);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
else
{
Console.WriteLine("Error with feed");
}
}

Related

How can I call the method that is in my Hub from my controller on ASP.NET Core?

I'm using SignalR and I my hub is on a folder called Hubs. I need to call the method that's in my Hub "PostMarker()" on my controller. So, everytime something is posted, the SignalR updates all windows open. How should I do that?
[HttpPost]
public async Task<IActionResult> PostOcorrencias([FromBody] Ocorrencias ocorrencia, IFormFile UploadImag)
{
ocorrencia.DataOcorrencia = DateTime.Now;
//processar a fotografia
//ocorrencia.Fotografia = "(nome fotografia)";
string caminho = "";
if (UploadImag == null)
{
return BadRequest(ModelState);
}
else
{
if (UploadImag.ContentType == "imagens/jpg" ||
UploadImag.ContentType == "imagens/png")
{
string extensao = Path.GetExtension(UploadImag.FileName).ToLower();
Guid g;
g = Guid.NewGuid();
string nome = g.ToString() + extensao;
caminho = Path.Combine(environment.WebRootPath,"imagens", nome);
ocorrencia.Fotografia = nome;
// Cria o ficheiro no sistema
using (var stream = new FileStream(caminho, FileMode.Create))
{
await UploadImag.CopyToAsync(stream);
}
}
}
_context.Ocorrencias.Add(ocorrencia);
//CALL HUB METHOD PostMarker()
await _context.SaveChangesAsync();
}
return CreatedAtAction("GetOcorrencias", new { id = ocorrencia.Id }, ocorrencia);
}
Here is my Hub:
public class MyHub : Hub
{
public async Task PostMarker()
{
await Clients.All.SendAsync("RedesignMap");
}
}
A SignalR IHubContext provides a means of sending messages to your clients outside of a Hub instance. The sample at https://learn.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-3.1 provides an example. Using the code there as a starting point, you can:
Inject the IHubContext into your controller, assuming that it is named HomeController:
public class HomeController : Controller
{
private readonly IHubContext<MyHub> _hubContext;
public HomeController(IHubContext<MyHub> hubContext)
{
_hubContext = hubContext;
}
}
Use the hub context in your PostOcorrencias controller action:
...
_context.Ocorrencias.Add(ocorrencia);
await _hubContext.Clients.All.SendAsync("RedesignMap");
await _context.SaveChangesAsync();
...

Unit Test with Asp.Net Web Api and customer filter

I am working on the Unit Testing in Asp.Net Mvc Web Api.
I have 2 projects
1: Catalog.Api - This contains all the controllers
2: Catalog.UnitTests - This contains the Unit Test for controllers
All Controllers are Inherit with "ApiController" and every controller has custom filter [AuthenticationFilter]. Here is my values controller.
[AuthenticationFilter]
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
And my custom is check the authorization token. Here it is
public class AuthenticationFilter: AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
var request = actionContext.Request;
var authorization = request.Headers.Authorization;
if (authorization == null || authorization.Scheme != "Bearer")
{
ShowAuthenticationError(actionContext, "Authorization required");
return;
}
if (string.IsNullOrEmpty(authorization.Parameter))
{
ShowAuthenticationError(actionContext, "Missing Jwt Token");
return;
}
var token = authorization.Parameter;
var principal = AuthenticateToken(token);
if (principal == null)
{
ShowAuthenticationError(actionContext, "Invalid token");
return;
}
base.OnAuthorization(actionContext);
}
private static void ShowAuthenticationError(HttpActionContext filterContext, string message)
{
var responseDTO = new ResponseDTO() { Code = 401, Message = message };
filterContext.Response =
filterContext.Request.CreateResponse(HttpStatusCode.Unauthorized, responseDTO);
}
}
public class ResponseDTO
{
public int Code { get; set; }
public string Message { get; set; }
}
Now in the Unit Test project i have a class and unit test method.
[TestMethod]
public void CheckFilter()
{
try
{
var controller = new ValuesController();
var controllerContext = new HttpControllerContext();
var request = new HttpRequestMessage();
request.Headers.Add("Authorization", "bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6InVhbGkiLCJlbWFpbCI6InVhbGlAaW5yZWFjaGNlLmNvbSIsIm5iZiI6MTU2NDY0NjIyMSwiZXhwI");
controllerContext.Request = request;
controller.ControllerContext = controllerContext;
var result = controller.Get();
Assert.IsTrue(result.Any());
}
catch (Exception ex)
{
Assert.Fail();
}
}
I am calling my controller by adding reference of API project into my unit test project. So all controllers are available in the unit test project.
Issue is that when i call the values controller it always return the data. And when i remove the request and header so it is also returning the data but in that case that will be unauthorized.
I think my custom filter is not calling. How should that would be called and authenticate the user.
I check your question and configure that issue it is basically you are calling the controller directly.
Basically controller is a class and when you are calling that it is behaving like a simple class and call the method and send back the result. It is simple and clear
But in your situation you have project for your api so can do this.
[TestMethod]
public void CheckFilter()
{
try
{
var config = new HttpConfiguration();
// This is the resgister method which is written in you Api project. That code is after this method this method because i did the same thing to call my controller.
Catalog.Api.WebApiConfig.Register(config);
using (var server = new HttpServer(config))
{
var client = new HttpClient(server);
string url = "http://localhost:PortNumberOfProject/api/values";
var request = new HttpRequestMessage
{
RequestUri = new Uri(url),
Method = HttpMethod.Get
};
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "Your Token");
var response = await client.SendAsync(request);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
}
catch (Exception ex)
{
Assert.Fail();
}
}
Here is the WebApi Register method of Api project which is used to register the Api and Routes.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Here is your controller as it is. And now debug your test and add a break point in your [AuthenticationFilter] and OnAuthorization method.
[AuthenticationFilter]
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}

HttpClient is sending NULL in web Api in mvc5

HttpClient is sending null values to controller while post and my code is here please help me
....................
using (HttpClient client=new HttpClient())
{
var parameters = ConvertToDictionary(tc);
client.BaseAddress = new Uri($"http://localhost:9797/");
var json = JsonConvert.SerializeObject(tc);
var data = new StringContent(content: json,encoding: Encoding.UTF8,mediaType: "application/json");
var response = client.PostAsync(api_url, data).GetAwaiter().GetResult();
var k = JsonConvert.DeserializeObject<Api>(response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
}
Thanks in advance
Try to use # insted of $ in client.BaseAddress. And check if tc object is not null.
I used Your code like this:
class Program
{
static void Main(string[] args)
{
using (HttpClient client=new HttpClient())
{
client.BaseAddress = new Uri(#"http://localhost:61737/api/presidents");
var json = JsonConvert.SerializeObject(new { name = "name", value = "value" });
var data = new StringContent(content: json,encoding: Encoding.UTF8,mediaType: "application/json");
var response = client.PostAsync(#"http://localhost:61737/api/presidents/post", data).GetAwaiter().GetResult();
var k = (response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
}
}
}
And controller looks like this:
[RoutePrefix("api/presidents")]
public class PresidentsController : ApiController
{
public class oooo
{
public string Name { get; set; }
public string Value { get; set; }
}
[Route("post")]
public IHttpActionResult Post(oooo o)
{
return Ok(o);
}
}
and everything is working.

Object is null when passed to web api in c#

I have created web api in asp.net mvc. What I want is to call that post method in web api from another project (website) in asp.net.
Here is my Class Vendor
[ModelBinder(typeof(VendorModelBinder))]
public class Vendor
{
public string VenName { get; set; }
public string VenCompany { get; set; }
}
Here is VendorModelBinder
public class VendorModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(Vendor))
{
return false;
}
Vendor result = JsonConvert.DeserializeObject<Vendor>
(actionContext.Request.Content.ReadAsStringAsync().Result);
bindingContext.Model = result;
return true;
}
Here is my VendorController
public class VendorController : ApiController
{
// POST: api/Vendor/5
[HttpPost]
[Route("")]
public HttpResponseMessage Post([ModelBinder]Vendor Ven)
{
SqlConnection con = new SqlConnection(" Data Source = DELL; Initial Catalog = EVENT; Integrated Security = True");
SqlCommand com = new SqlCommand("[dbo].[InsVendor]", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#user", Ven.VenName);
com.Parameters.AddWithValue("#compnay", Ven.VenCompany);
con.Open();
int i = com.ExecuteNonQuery();
con.Close();
HttpResponseMessage message = Request.CreateResponse(HttpStatusCode.OK);
message.Content = content;
return message;
}
}
Here I am calling the post method in web api
static async Task<Uri> AddVendorAsync(AllVendor Ven)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:56908/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
StringContent content = new StringContent(JsonConvert.SerializeObject(Ven), Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync("api/Vendor", content);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
// return URI of the created resource.
return response.Headers.Location;
}
}
Is the above procedure correct?
Because I am getting the null object at the Vendor Controller (Ven.VenName)
Kindly, help me on this one.
Thanks.

Bundling with application cache in MVC4

I am working with an MVC project. And I use the application cache to store my whole page to the cache so that the application is still available even offline.
This is my Offline Controller
public class OfflineController : Controller
{
//
// GET: /Offline/
public ActionResult Index()
{
var manifestResult = new ManifestResult("1.0")
{
CacheResources = new List<string>()
{
Url.Action("Index", "Home"),
BundleTable.Bundles.ResolveBundleUrl("~/Content/css", true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/modernizr", true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/jquery",true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/jqueryui", true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/jqueryval",true),
BundleTable.Bundles.ResolveBundleUrl("~/bundles/modernizr",true),
BundleTable.Bundles.ResolveBundleUrl("~/Content/css",true),
BundleTable.Bundles.ResolveBundleUrl("~/Content/themes/base/css")
},
NetworkResources = new string[] { "*" },
FallbackResources = { { "Images/offline.jpg", "Images/offline.jpg" } }
};
return manifestResult;
}
}
My Home Controller is this
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
return View();
}
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult Contact()
{
ViewBag.Message = "Your contact page.";
return View();
}
}
This is my class that generate the manifest file
public class ManifestResult : FileResult
{
public ManifestResult(string version)
: base("text/cache-manifest")
{
Version = version;
CacheResources = new List<string>();
NetworkResources = new List<string>();
FallbackResources = new Dictionary<string, string>();
}
public string Version { get; set; }
public IEnumerable<string> CacheResources { get; set; }
public IEnumerable<string> NetworkResources { get; set; }
public Dictionary<string, string> FallbackResources { get; set; }
protected override void WriteFile(HttpResponseBase response)
{
WriteManifestHeader(response);
WriteCacheResources(response);
WriteNetwork(response);
WriteFallback(response);
}
private void WriteManifestHeader(HttpResponseBase response)
{
response.Output.WriteLine("CACHE MANIFEST");
response.Output.WriteLine("#V" + Version ?? string.Empty);
}
private void WriteCacheResources(HttpResponseBase response)
{
response.Output.WriteLine("CACHE:");
foreach (var cacheResource in CacheResources)
response.Output.WriteLine(cacheResource);
}
private void WriteNetwork(HttpResponseBase response)
{
response.Output.WriteLine();
response.Output.WriteLine("NETWORK:");
foreach (var networkResource in NetworkResources)
response.Output.WriteLine(networkResource);
}
private void WriteFallback(HttpResponseBase response)
{
response.Output.WriteLine();
response.Output.WriteLine("FALLBACK:");
foreach (var fallbackResource in FallbackResources)
response.Output.WriteLine(fallbackResource.Key + " " + fallbackResource.Value);
}
}
Here is the error that I encounter
Before I answer, for those of you that just landed here, this is the implementation/article being referenced:
http://www.infoq.com/articles/Offline-Web-Apps
I was able to get this working just fine. One difference between your implementation and mine is that you are listing your manifest as such in the HTML tag:
<html manifest="/Offline">
.. or so I'm guessing.. you didn't post your HTML. I am not sure that HTML tag will be properly interpreted. Here is what I am using and works fine:
<html manifest="/Mobile/Manifest">
My guess is that "Application Cache Error event: Manifest fetch failed (-1)" is the equivalent of a 404.
Hope this helps... I see it's been quite a while since you posted.
I encountered the same issue of the css and script resources not loading in offline mode, when using the same infoq blog post as an example. I resolved the issue by adding the script and css resources using Scripts.Url instead of BundleTable.Bundles.ResolveBundleUrl.
My solution is based on a blog post by Eoin Clayton.
Using the Offline controller code you posted as a base, it may work if you modify it to look as follows:
public class OfflineController : Controller
{
//
// GET: /Offline/
public ActionResult Index()
{
var manifestResult = new ManifestResult("1.0")
{
CacheResources = new List<string>()
{
Url.Action("Index", "Home"),
Scripts.Url("~/bundles/jquery").ToString(),
Scripts.Url("~/bundles/modernizr").ToString(),
Scripts.Url("~/bundles/bootstrap").ToString(),
Scripts.Url("~/Content/css").ToString()
},
NetworkResources = new string[] { "*" },
FallbackResources = { { "Images/offline.jpg", "Images/offline.jpg" } }
};
return manifestResult;
}
}
Hope this helps.

Resources