I am currently using python requests to consume a web api written in c# within my MVC application. This is the error I get
<body>
<div id="header"><h1>Server Error</h1></div>
<div id="content">
<div class="content-container"><fieldset>
<h2>405 - HTTP verb used to access this page is not allowed.</h2>
<h3>The page you are looking for cannot be displayed because an invalid method (HTTP verb) was used to attempt access.</h3>
</fieldset></div>
</div>
</body>
and here is the python code I am using
constURLString = "http://10.1.30.15/test/api/DevicesAPI"
send = requests.put(constURLString + "/" + str(deviceID), data = urlParam)
urlParam is the model I am passing back to the webapi in order to edit that specific entry. I tried typing the actual url into my browser trying to get that single entry by typing http://10.1.30.15/test/api/DevicesAPI/16 and got
<Error><Message>An error has occurred.</Message></Error>
Which isn't very helpful. This seems to work perfectly when I am running it locally but doesn't seem to like it when I publish it to the server. My put method within my web api goes as is:
// PUT: api/DevicesAPI/5
[ResponseType(typeof(void))]
public IHttpActionResult PutDevices(long id, Devices devices)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != devices.deviceID)
{
return BadRequest();
}
db.Entry(devices).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!DevicesExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
Related
I am facing a weird problem. In my Azure mobile app, I added a plain vanilla webapi controller with standard http verbs get, put etc. Now on my localhost everything is working fine. but when I deploy this to my azurewebsite. and call using Post man. the PUT request gets mapped to GET code. I tested using Postman, fiddler.
I am sure I am missing sth, but couldn't figure it out, checked the route, tried multiple options, but just couldn't figure out. Same is true with DELETE and POST. below is the sample code
[MobileAppController]
public class TestController : BaseController
{
// GET: api/Test
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET: api/Test/5
public string Get(int id)
{
return "value";
}
// POST: api/Test
[Route("api/test")]
public async Task<string> Post([FromBody]string value)
{
await Task.Delay(100);
return "post: " + value;
}
// PUT: api/Test/5
[Route("api/test/{id}")]
public async Task<string> Put(int id, [FromBody]string value)
{
await Task.Delay(100);
return "put: " + value;
}
// DELETE: api/Test/5
[Route("api/test/{id}")]
public async Task<string> Delete(int id)
{
await Task.Delay(100);
return "delete: " + id;
}
You are mixing routing via WebAPI and routing via Mobile Apps, and they are conflicting. Pick one. For this application, I'd suggest removing the MobileAppController attribute and just going with the WebAPI routing.
Make sure you are making request via SSL i.e. your url should be starting from https.
when I was using Postman, my url was starting with "http" and any POST/PUT/DELETE request gets mapped to GET. and if I change it to "https" everything just works as expected.
I am calling a spring controller method from dojo xhrPost and I need to redirect to a new html from the controller method. But controller returns back to the dojo in javascript instead of moving to a new page.
my javascript:
var xhrArgs={
url:"/tradeIn/submitTradeIn",
postData:dojo.toJson(tradeInDetails),
handleAs:"text",
headers:{"Content-Type":"application/json"}
/*load:function(data){
console.log(data);
label=data;
if(data =="fail"){
location.reload(true);
window.location="/Fail";
}
else{
window.location="/success";
}
}*/
}
var deferred=dojo.xhrPost(xhrArgs);
my spring controller:
#RequestMapping(value="/tradeIn/submitTradeIn", method = {RequestMethod.POST})
public String submitTradeIn(#RequestBody TradeInDetails tradeDetails) throws UnsupportedEncodingException{
List<byte[]> labelList=new ArrayList<byte[]>();
ShippingInfo shippingInfo=new ShippingInfo();
shippingInfo.setAddress1(tradeDetails.getCustomerDetails().get(0).getAddress1());
shippingInfo.setAddress2(tradeDetails.getCustomerDetails().get(0).getAddress1());
shippingInfo.setCity(tradeDetails.getCustomerDetails().get(0).getCity());
shippingInfo.setCompany(tradeDetails.getCustomerDetails().get(0).getCompany());
shippingInfo.setDayPhone(tradeDetails.getCustomerDetails().get(0).getDayPhone());
shippingInfo.setEmail(tradeDetails.getCustomerDetails().get(0).getEmail());
shippingInfo.setEvePhone(tradeDetails.getCustomerDetails().get(0).getEvePhone());
shippingInfo.setFirstName(tradeDetails.getCustomerDetails().get(0).getFirstName());
shippingInfo.setLastName(tradeDetails.getCustomerDetails().get(0).getLastName());
shippingInfo.setState(tradeDetails.getCustomerDetails().get(0).getState());
shippingInfo.setZip(tradeDetails.getCustomerDetails().get(0).getZip());
shippingInfo.setCountry(tradeDetails.getCustomerDetails().get(0).getCountry());
List<ReturnRequestLabel> label;
List<TradeInClubs> tradeInList1= new ArrayList<TradeInClubs>();
for(ClubDetails cl: tradeDetails.getClubDetails()){
TradeInClubs tradeInclubs1=new TradeInClubs();
tradeInclubs1.setClubMaterial(cl.getShaftType());
tradeInclubs1.setClubType(cl.getClubType());
tradeInclubs1.setManufacturer(cl.getClubManufacturer());
tradeInclubs1.setModel(cl.getClubModel());
tradeInclubs1.setTradeInValue(cl.getTradeInPrice());
tradeInList1.add(tradeInclubs1);
}
try{
ReturnFedexLabel returnFedexLabel = new ReturnFedexLabel();
label=returnFedexLabel.fetchFedexLabel(tradeInList1, shippingInfo);
byte[] labelImageData;
String fedexLabelNumber=null;
for(ReturnRequestLabel rl: label){
labelImageData=rl.fedexReturnLabel.imageData;
labelList.add(labelImageData);
fedexLabelNumber=rl.trackingNumber;
}
File f=new File("label.jpg");
BufferedImage img=ImageIO.read(new ByteArrayInputStream(labelList.get(0)));
ImageIO.write(img,"JPEG",f);
int id=tradeInDao.insertQuery(shippingInfo,tradeInList1,fedexLabelNumber);
byte[] pdfData=fedexLabelToPdf.printFedexLabel(labelList);
emailTradeIn.emailTradeInDetails(pdfData,tradeDetails.getCustomerDetails().get(0).getEmail(),tradeInList1,id);
System.out.println("here");
} catch (Exception e){
logger.error(e.getMessage());
return "fail";
}
return "success";//Base64.encodeBase64String(labelList.get(0));
}
it is not moving to success page. it just stays in the current page
Check and see what deferred is, it is probably "success".
From http://dojotoolkit.org/reference-guide/1.7/quickstart/ajax.html:
dojo.xhrPost xhrPost will create an Ajax request using the HTTP POST
method and is usually used to submit data to a service. It returns
data to a callback. The callback is defined as a member of the object
used to create the request (the property-bag), or by using the
dojo.Deferred.then() method.
For complete details and examples, see the dojo.xhrPost documentation.
if you need to change the page from the controller it shouldn't be an ajax request. If you can change it from the client side then you can continue with the ajax request and respond accordingly.
we made an web app using vs 2010 mvc 4, that displays product catelougue to users, we have also created cart system for the same. But whenever user submits cart We are displaying view, but URL remains same,
before posting data to action CheckOut URL is :
www.domain.com/shoppingcart/checkout
after posting data to action Checkout URL is same as mentioned. What I need to accomplish is Change "www.domain.com/shoppingcart/checkout" this URL to "www.domain.com/products" so even if user refreshes the page He/she cannot place the same order Twice or more times.
my post method is form post. No ajax calls have been made to post form.
Any suggestions?
[HttpPost]
public ActionResult CheckOut(Order order)
{
try
{
//.. some code
}
catch (Exception e)
{
HandleErrorInfo err = new HandleErrorInfo(e, "ShoppingCart", "CheckOut");
return View("Error", err);
}
return View("OrderPlaced", order);
}
Can I Do something like this?
[DisplayURL(URL="www.domain.com/Products/Catelouge")]
[HttpPost]
public ActionResult CheckOut(Order order)
{
try
{
//.. some code
}
catch (Exception e)
{
HandleErrorInfo err = new HandleErrorInfo(e, "ShoppingCart", "CheckOut");
return View("Error", err);
}
return View("OrderPlaced", order);
}
Can't you just redirect to a new page:
return Redirect("Home/MyNewPage");
Solution was suggested by Stephen Muecke.
To use PRG pattern to redirect to another method or to avoid unnecessary calls to action methods. Thanks Stephen
I'm having a problem with consuming OData Services using Breeze, I set up a Web API OData service by following this guide, from Fiddler it works excellent as expected, but when I try to use it with breeze it fails and gives an error message of "OK":
[Q] Unhandled rejection reasons (should be empty):Error: OK
Using fiddler I see it goes and queries for metadata and then it queries for the entities which are returned correctly, what could be the problem here?
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager(serverAddress);
var query = new breeze.EntityQuery.from("Laboratories");
manager.executeQuery(query).then(function (data) {
ko.applyBindings(data);
}).fail(function (e) {
alert(e);
});
I enabled CORS by using the nightly build of ASP.NET Web API CORS support, it all works fine and I can retrieve the entities since I can see in fiddler that they are returned ... it's just that it doesn't go to the then promise instead it lands in fail.
UPDATE:
In response to #Ward testing from newly created projects I did the following:
PROJECT 1
Created a Web API Project.
Added Microsoft ASP.MET Web API Cross-Origin Resource Sharing (CORS) Reference from Nuget.
Added the following Controller:
namespace CORSBreezeTest1.Controllers
{
public class ValuesController : EntitySetController<Value, int>
{
ValuesDbContext _context = new ValuesDbContext();
[Queryable]
public override IQueryable<Value> Get()
{
return _context.Values;
}
protected override Value GetEntityByKey(int key)
{
return _context.Values.Find(key);
}
protected override Value CreateEntity(Value entity)
{
Value value = _context.Values.Find(entity.Id);
if (value != null)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Conflict));
}
_context.Values.Add(entity);
_context.SaveChanges();
return entity;
}
protected override int GetKey(Value entity)
{
return entity.Id;
}
protected override void Dispose(bool disposing)
{
_context.Dispose();
base.Dispose(disposing);
}
}
}
And the following Code First Database:
namespace CORSBreezeTest1
{
public class ValuesDbContext : DbContext
{
public ValuesDbContext()
: base("DefaultConnection")
{
}
public DbSet<Value> Values { get; set; }
}
public class Value
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
}
}
Added the following lines in WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
// Default code left out here ...
config.Routes.MapODataRoute("Values", "odata", GetEdmModel());
config.EnableQuerySupport();
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
}
private static IEdmModel GetEdmModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.Namespace = "CORSBreezeTest1";
builder.EntitySet<Value>("Values");
return builder.GetEdmModel();
}
PROJECT 2
Then created another Web API Project.
Added Breeze for ASP.NET Web API Projects Nuget Package
Added datajs Nuget Package.
Added the following lines of code to Index.cshtml:
<p data-bind="visible: !results">Fetching data ... </p>
<ul data-bind="foreach: results, visible: results" style="display: none">
<li>
<span data-bind="text: Name"></span>
<span data-bind="text: Quantity"></span>
</li>
</ul>
#section Scripts {
<script src="~/Scripts/knockout-2.2.0.debug.js"></script>
<script src="~/Scripts/q.js"></script>
<script src="~/Scripts/datajs-1.1.0.js"></script>
<script src="~/Scripts/breeze.min.js"></script>
<script type="text/javascript">
$(function () {
breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager("http://serverAddress/odata")
var query = new breeze.EntityQuery.from("Values");
manager.executeQuery(query).then(function (data) {
ko.applyBindings(data);
}).fail(function (e) {
alert(e);
});
});
</script>
}
Tested as is and it worked since both websites are on localhost.
Published PROJECT 1 to a web server so that the test will actually see different origins, and tested.
And this is what Nugget saw:
The first request headers are OPTIONS
OPTIONS /odata/Values HTTP/1.1
And the second request headers are GET
GET /odata/Values HTTP/1.1
And if I change my fail code to:
fail(function (e) {
ko.applyBindings(e.body.value);
});
And my knockout code to:
<p data-bind="visible: !$data">Fetching data ... </p>
<ul data-bind="foreach: $data, visible: $data" style="display: none">
<li>
<span data-bind="text: Name"></span>
<span data-bind="text: Quantity"></span>
</li>
</ul>
Voila! It came through with the data:
And this is what the Console saw:
SEC7118: XMLHttpRequest for http://serverAddress/odata/$metadata required Cross Origin Resource Sharing (CORS).
localhost:53317
SEC7119: XMLHttpRequest for http://serverAddress/odata/$metadata required CORS preflight.
localhost:53317
SEC7118: XMLHttpRequest for http://serverAddress/odata/Values required Cross Origin Resource Sharing (CORS).
localhost:53317
SEC7119: XMLHttpRequest for http://serverAddress/odata/Values required CORS preflight.
localhost:53317
[Q] Unhandled rejection reasons (should be empty):Error: OK
PROJECTS 1 & 2 using the BreezeControllerAttribute
If I in another test add a new controller following Breeze Nuget example and add Breeze for ASP.NET Web API project Nuget package and add the following controller:
namespace CORSBreezeTest1.Controllers
{
[BreezeController]
public class BreezeValuesController : ApiController
{
readonly EFContextProvider<ValuesDbContext> _context =
new EFContextProvider<ValuesDbContext>();
[HttpGet]
public string Metadata()
{
return _context.Metadata();
}
[HttpGet]
public IQueryable<Value> Values()
{
return _context.Context.Values;
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _context.SaveChanges(saveBundle);
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
}
}
And then modify the client as following:
//breeze.config.initializeAdapterInstances({ dataService: "OData" });
var manager = new breeze.EntityManager("http://serverAddress/breeze/BreezeValues")
Then the requests change:
And everything works ... I'm not sure if in part is something that EntitySetController handles requests differently or is Breeze making different requests when changing the dataService.
I don't know the answer yet. But there are a couple of misunderstandings in your question. First, CORS is a browser convention. It is a (relatively) safe way to work around the browser "Same Origin" policy.
That's a browser policy. Fiddler is not a browser. It is not constrained by "Same Origin" policies and can happily read and write across domain. So you can't tell if the server is properly configured for CORS based on what happens in Fiddler.
And of course "the same code in the same site that hosts the Web API works flawlessly"; you aren't violating the "Same Origin" policy so CORS is not involved.
You need to test your server configuration by writing a browser client application that launches from a site other than the host of your Web API. It doesn't have to be a breeze client. A simple AJAX call to an endpoint will do. You might as well write another simple, non-Breeze Web API controller while you're at it. Keep both controllers really simple. Keep your test client really simple.
My bet is that you will have the same trouble with both breeze-enabled and vanilla Web API controller. You'll power through that. And when you do, it should work for both the breeze and vanilla controllers. If you can show that your client works with one but not the other, come back and give us the code.
Sorry for your pains.
The only way to get it to work was to use the BreezeControllerAttribute from Breeze.WebApi following the breeze exact way of using the api. Not using EntitySetController and going back to a regular ApiController. Detailed explanation in the question itself.
[BreezeController]
public class BreezeValuesController : ApiController
{
// Methods here
}
You just need to add this extra parameter DataServiceVersion, MaxDataServiceVersion configuring enableCors.
config.EnableCors(new EnableCorsAttribute("*", "*", "*", "DataServiceVersion, MaxDataServiceVersion"));
Id like to use Watin to get html snapshots to make my single page ajax app crawlable as per google specifications.
Can somebody please show me code example how to return an html snapshot to googlebot using Watin?
This is what I have so far but honestly Im not even sure where Im going with this I really havent found a single example on the web that would really clear it up:
Controller:
public PartialViewResult Solutions()
{
//Googlebot request
HtmlString htmlSnapshot = (HtmlString)GetHtmlSnapshot(Request.Path);
//return ?????????
//Normal user request
return PartialView("Solutions", null);
}
public PartialViewResult MarketData()
{
return PartialView("MarketData", null);
}
public IHtmlString GetHtmlSnapshot(string uglyUrl)
{
if (uglyUrl.Contains("?_escaped_fragment_="))
{
string prettyUrl = uglyUrl.Replace("?_escaped_fragment=", "");
string decodedUrl = HttpUtility.UrlDecode(prettyUrl);
FireFox firefox = new FireFox();
firefox.GoTo(decodedUrl);
//?????????
}
}