I just started learning c#, ASP.net, and I have this issue. This is the code. I have a model in the models folder called Role.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace xrakFRS.Models {
public class Role {
[Key]
public int ID { get; set; }
public string Rolename { get; set; }
public string Description { get; set; }
}
}
This is my RolesController
using xrakFRS.Data;
using xrakFRS.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;
namespace xrakFRS.Controllers {
[EnableCors("*", "*", "*"), RoutePrefix("api/roles")]
public class RolesController : ApiController{
[HttpGet]
[Route("getroles")]
public IHttpActionResult GetRoles() {
try {
using (var context = new AppDbContext()) {
var entries = context.Roles.ToList();
return Ok(entries);
}
} catch (Exception ex) {
return BadRequest(ex.Message);
}
}
[HttpPost]
[Route("postrole")]
public IHttpActionResult PostRole([FromBody] Role role) {
if (!ModelState.IsValid) return BadRequest(ModelState);
try {
using (var context = new AppDbContext()) {
context.Roles.Add(role);
context.SaveChanges();
return Ok("Entry was created");
}
} catch (Exception ex) {
return BadRequest(ex.Message);
}
}
When I try to call the api using Postman, I get this:
When I try to inspect the variables at the breakpoints, I get null values:
I get null values for "Rolename" and "Description". I am not sure why my data is not binding on the controller.
try sending raw body from Postman
{
"rolename": "Admin user for the application",
"description": "Administrator"
}
go to postman body-> select raw and from dropdown menu json
then go to body and add
{
"roleId":1,
"rolename":" bla bla",
"description" : " bla bla"
}
Try using x-www-form-urlencoded via postman and remove [FromBody] attribute. It will automatically map varriables to the object. The code will look like:
[HttpPost]
[Route("postrole")]
public IHttpActionResult PostRole(Role role) {
//Any logic here
}
How the request should look like in the Postman
Postman should look like this
Related
I'm having a problem trying to upload a post on my development blog. I'm trying to upload a Post by using the MVC framework. I'm trying to follow a broad number of guides as to how to build a blog.
Here's the Post class
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace ProjectWebApp.Models
{
public class Post
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PostID { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Content { get; set; }
public string Author { get; set; }
public int Likes { get; set; }
[Required]
public DateTime DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
public ICollection<PostTag> PostTags { get; set; }
}
}
and here's the BlogDBContext:
using Project.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ProjectBlogWebApp.Data
{
public class BlogDbContext : DbContext
{
public BlogDbContext(DbContextOptions<BlogDbContext> options) : base(options)
{
Database.EnsureDeleted();
if (Database.EnsureCreated() == true)
{
Database.EnsureCreated();
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PostTag>().HasKey(p => new {p.PostID, p.TagID});
modelBuilder.Entity<PostTag>().HasOne(pt => pt.Post).WithMany(p => p.PostTags)
.HasForeignKey(pt => pt.PostID);
modelBuilder.Entity<PostTag>().HasOne(pt => pt.Tag).WithMany(t => t.PostTags)
.HasForeignKey(pt => pt.TagID);
}
public DbSet<Post> Posts { get; set; }
public DbSet<Tag> Tags { get; set; }
public DbSet<PostTag> PostTags { get; set; }
}
}
Here's the PostController class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ProjectWebApp.Data;
using ProjectWebApp.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.EntityFrameworkCore;
namespace ProjectWebApp.Controllers
{
public class PostController : Controller
{
private BlogDbContext _dbBlogContext;
public PostController(BlogDbContext dbContext)
{
_dbBlogContext = dbContext;
}
public IActionResult Index()
{
var postList = _dbBlogContext.Posts.ToList();
return View(postList);
}
[HttpGet, Route("Create")]
public IActionResult Create()
{
return View(new Post());
}
[HttpGet, Route("Edit")]
public IActionResult Edit()
{
return View();
}
[HttpPost]
public async Task<IActionResult> CreatePostAsync([Bind("Title", "Content")] Post post)
{
try
{
post.Likes = 0;
post.DateCreated = DateTime.Now;
post.Author = "Leonard Morrison";
_dbBlogContext.Add(post);
await _dbBlogContext.SaveChangesAsync();
}
catch (DbUpdateException)
{
ModelState.TryAddModelError( "Error: Post was not added properly!", "Sorry, the Post was not added properly. Please let me know if this problem persists");
}
return View(post);
}
[HttpGet]
public IActionResult Show(int ID)
{
var post = getPost(ID);
return View(post);
}
[HttpGet]
public IActionResult Edit(int ID)
{
var post = getPost(ID);
return View(post);
}
[HttpPatch]
public IActionResult Update(int id)
{
var post = _dbBlogContext.Posts.Find(id);
_dbBlogContext.Posts.Update(post);
return RedirectToAction("Index");
}
[HttpDelete]
public IActionResult RemovePost(int id)
{
Post deletedPost = getPost(id);
_dbBlogContext.Posts.Remove(deletedPost);
_dbBlogContext.SaveChanges();
return RedirectToAction("Index");
}
public Post getPost(int ID)
{
var post = _dbBlogContext.Posts.First(p => p.PostID == ID);
return post;
}
}
}
and lastly, here's the Startup source code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ProjectWebApp.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http;
namespace ProjectBlogWebApp
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<BlogDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<BlogDbContext, BlogDbContext>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
//The Main EndPoint Routes
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id}");
});
//The Post Endpoints Routes
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "post",
pattern: "{controller=Post}/{action=Index}/{title?}");
});
}
}
}
Because I don't know where exactly the error is. But I need to where this 405 Error is coming from.
Thanks.
The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed response status code indicates that the request method is known by the server but is not supported by the target resource.
The generate Url is "localhost:5001/Create", which only match the Create Get method, while the form send a HttpPost Request, so it occurs 405 error.
1.You may add a asp-action="CreatePost" on your form tag,
2.Or just add a same Route Attribute on your CreatePost action
[HttpPost]
[Route("Create")]
public async Task<IActionResult> CreatePostAsync([Bind("Title", "Content")] Post post)
Check your Create View (Create.cshtml) to ensure asp-action="CreatePostAsync" in your form tag.
If that's not the problem, please include your View code as well.
Also put a breakpoint at CreatePostAsync and follow along to see where the error occurs. It's possible the action isn't being triggered. Which means, your breakpoint won't be triggered either.
Few other things that may help either with the problem and/or project:
BlogDbContext: OnModelCreating(), those codes are to indicate foreignkeys? The ForeignKeys will be automatically created/mapped by EF as long as the property name is {TableName}Id. You can also be explicit by using [ForeignKey] attribute to the ForeignKey
Controller: You can combine Method and Route [HttpGet("Create")]. I'm certain this isn't the problem but just wanted to let you know
Create(): Don't need to pass new Post model to view() since your view will already have "#model Post"
CreatePostAsync(): I'd suggest creating a PostViewModel with the necessary properties and the validation checks. Use the PostViewModel as the parameter. This also means you'll need to update your Create view from #model Post to #model PostViewModel
CreatePostAsync(): Always redirect a post method back to get after it's done processing. Only time you should return View() would be if there are errors. Otherwise, a user can spam refresh and create multiple lines of data. Try it for yourself actually once you get the Create working
I have an error in this code. I deserialize a JSON file and stored that data in the database now I want to show that data from my database.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Helpers;
using System.Web.Mvc;
using ReadingFromDb.Dto;
namespace ReadingFromDb.Controller
{
public class StudentController
{
[HttpGet]
[AllowAnonymous]
public async Task<JsonResult> GetStudents()
{
using (var context = new UNIEntities1())
{
var query = #"Select ";
var dbQuery = context.Database.SqlQuery<StudentDto>(query);
var list = await dbQuery.ToListAsync();
return Json(list,JsonRequestBehavior.AllowGet);
}
}
}
}
Error is:
JSON can not be used like method.
What should I do?
Your contoller must be extend the base class Controller in which the Json() virtual method is available:
public class StudentController : Controller
{
// your code
}
To resolve this error you can try as below
public class StudentController : Controller
{
// your code
}
[HttpGet]
[AllowAnonymous]
public async Task<JsonResult> GetStudents()
{
using (var context = new UNIEntities1())
{
var list = await context.StudentDto.ToListAsync();
return Json(list,JsonRequestBehavior.AllowGet);
}
}
What you need to do is to extend your StudentCotroller with Controller then put your code under that.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Web.Helpers;
using System.Web.Mvc;
using ReadingFromDb.Dto;
namespace ReadingFromDb.Controller
{
public class StudentController:Controller
{
[HttpGet]
[AllowAnonymous]
public async Task<JsonResult> GetStudents()
{
using (var context = new UNIEntities1())
{
var query = #"Select ";
var dbQuery = context.Database.SqlQuery<StudentDto>(query);
var list = await dbQuery.ToListAsync();
return Json(list,JsonRequestBehavior.AllowGet);
}
}
}
}
I am receiving the following error: The name 'Ok' does not exist in the current context.
How would I resolve this issue in my Controller API? Return Ok is already embedded in the controller.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using System.Net.Http;
using Newtonsoft.Json;
using WeatherTest.Models;
namespace WeatherChecker.Controllers
{
public class WeatherData
{
[HttpGet("[action]/{city}")]
public async Task<IActionResult> City(string city)
{
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("http://api.openweathermap.org");
var response = await client.GetAsync($"/data/2.5/weather?q={city}&appid=YOUR_API_KEY_HERE&units=metric");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
var rawWeather = JsonConvert.DeserializeObject<OpenWeatherResponse>(stringResult);
// Error Here: ** The name 'Ok' does not exist in the current context **
return Ok(new
{
Temp = rawWeather.Main.Temp,
Summary = string.Join(",", rawWeather.Weather.Select(x => x.Main)),
City = rawWeather.Name
});
}
catch (HttpRequestException httpRequestException)
{
// Error Here: The name 'BadRequest' does not exist in the current context
return BadRequest($"Error getting weather from OpenWeather: {httpRequestException.Message}");
}
}
}
}
}
With Attribute routing feature, aspnet support POCO controller. It allow to use any class as controller. But you will we lose all utilities and helpers provided by framework base classes.
The class Controller inherite from ControllerBase and add view support. In your case, ControllerBase is enough.
public class WeatherData : ControllerBase // <-
{
// ...
}
i'm trying to get my apicontroller to work. But somehow i cannot return Json().
Here's the error message from the compiler:
Error CS0029 Cannot implicitly convert type
'System.Web.Http.Results.JsonResult<>'
to
'System.Web.Mvc.JsonResult' Opten.Polyglott.Web D:\Development\git\Opten.Polyglott\src\Opten.Polyglott.Web\Controllers\NewsletterApiController.cs
I cannot explain why it cannot convert the Json() to the ActionResult even the Json()inherits ActionResult.
Here's my controller:
using MailChimp;
using MailChimp.Helper;
using Opten.Polyglott.Web.Models;
using Opten.Umbraco.Common.Extensions;
using System.Configuration;
using System.Web.Mvc;
using Umbraco.Core.Logging;
using Umbraco.Web.WebApi;
namespace Opten.Polyglott.Web.Controllers
{
public class NewsletterApiController : UmbracoApiController
{
public ActionResult Subscribe(Newsletter newsletter)
{
bool isSuccessful = false;
if (ModelState.IsValid)
{
isSuccessful = SubscribeEmail(newsletter.Email);
}
return Json(new { isSuccess = isSuccessful });
}
}
}
Thanks for any help.
Your problem is within the usings as the UmbracoApiController most likely inherits from ApiController (from System.Web.Http) not Controller (from System.Web.Mvc) and thus they have different dependencies. To fix your problem first remove the
using System.Web.Mvc;
and put the
using System.Web.Http;
as for the return in this case that would be IHttpActionResult so you would have something as follows:
using MailChimp;
using MailChimp.Helper;
using Opten.Polyglott.Web.Models;
using Opten.Umbraco.Common.Extensions;
using System.Configuration;
using System.Web.Http;
using Umbraco.Core.Logging;
using Umbraco.Web.WebApi;
namespace Opten.Polyglott.Web.Controllers
{
public class NewsletterApiController : UmbracoApiController
{
public IHttpActionResult Subscribe(Newsletter newsletter)
{
bool isSuccessful = false;
if (ModelState.IsValid)
{
isSuccessful = SubscribeEmail(newsletter.Email);
}
return Json(new { isSuccess = isSuccessful });
}
}
}
Let me know if that works for you.
It seems your Json is using class in System.Web.Http, not in System.Web.Mvc. In this case, you can use this code:
return new JsonResult{ isSuccess = isSuccessful };
When using ActionResult using Response.StatusCode is a good practice:
public ActionResult SomeMethod()
{
try
{
// ...
// doing something here...
// ...
// success:
Response.StatusCode = (int)HttpStatusCode.OK;
return Json(new { responseText = "OK" });
}
catch
{
// error:
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { responseText = "ERROR" });
}
}
Add the following line in your WebApiConfig.cs file:
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
I am trying to call a method in my Api Service:
public IQueryable Get(int UserId){
return UsersRepository.SelectAll().Where(ig => ig.Id == UserId);
}
from my HomeController:
UsersService.Get(UserId);
but I get this error: An object reference is required for the non-static field, method, or property 'CTHRC.Roti.Domain.Api.Services.UsersService.Get(int)'
What am I doing wrong? Here is my UserService:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CTHRC.Roti.Domain.Data.Repositories;
using CTHRC.Roti.Domain.Model;
namespace CTHRC.Roti.Domain.Api.Services
{
public class UsersService
{
protected readonly IUsersRepository UsersRepository;
public UsersService(IUsersRepository userRespository)
{
UsersRepository = userRespository;
}
public IQueryable Get(int UserId)
{
return UsersRepository.SelectAll().Where(ig => ig.Id == UserId);
}
}
}
and here is my Home Controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebMatrix.WebData;
using CTHRC.Roti.Domain.Model;
using CTHRC.Roti.Domain.Api.Services;
using CTHRC.Roti.Domain.Data.Repositories;
namespace CTHRC.Roti.Web.UI.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
if (!WebSecurity.IsAuthenticated)
{
Response.Redirect("~/account/login");
}
int UserId = 1;
UsersService.Get(UserId);
return View();
}
}
}
here is my IUsersRespository:
using System;
using System.Linq;
using CTHRC.Roti.Domain.Model;
namespace CTHRC.Roti.Domain.Data.Repositories
{
public interface IUsersRepository : IRepository<Users>
{
}
}
You are trying to call an instance method like a static method.
You have to instansiate UsersService in order to access the Get method:
public class HomeController : Controller
{
public ActionResult Index()
{
if (!WebSecurity.IsAuthenticated)
{
Response.Redirect("~/account/login");
}
int UserId = 1;
var service = new UsersService(userRepository);
service.Get(UserId);
return View();
}
}