Laravel Carbon error data missing with casting - laravel-6

I have a date property, and I try to cast it to the DateTime format during saving.
protected $casts = [
'date' => 'datetime:Y-m-d H:m',
];
In my controller, I have the following method.
public function change(int $gameSerieId, Request $request)
{
try {
$gameSerie = GameSerie::findOrFail($gameSerieId);
$gameSerie->update($request->all());
return response()->json('ok');
} catch (\Exception $exception) {
throw new GameApiException('Something went wrong!');
}
}
However, I get an error "Data Missing" because my date input format looks like a string: 2019-11-17 21:00.

I have found the ability of use mutators for set attributes
public function setDateAttribute($date)
{
$this->attributes['date'] = Carbon::make($date);
}
https://laravel.com/docs/5.7/eloquent-mutators#defining-a-mutator

Related

Trying to post an Array of Objects in Laravel. ErrorException: Creating default object from empty value in file

I'm trying to send a POST request with a data set like this:
[
{
"Course_Code":"CIS341",
"Start_Date":"2020-08-22",
"End_Date":"2020-12-02",
"CRN":345627,
"CWID":"C38475920",
"Date_Registered":"2020-04-02"
},
{
"Course_Code":"CIS341",
"Start_Date":"2020-08-22",
"End_Date":"2020-12-02",
"CRN":456392,
"CWID":"C38475920",
"Date_Registered":"2020-04-02"
},
{
"Course_Code":"CIS341",
"Start_Date":"2020-08-22",
"End_Date":"2020-12-02",
"CRN":562940,
"CWID":"C38475920",
"Date_Registered":"2020-04-02"
}
]
But I only want to insert the CRN, CWID, Date_Registered from each of those objects into my final_schedule table:
protected $table ="final_schedule";
public $timestamps = false;
protected $fillable = [
'CWID',
'CRN',
'Date_Registered'
];
Here is the insert function I'm using:
public function insert(Request $request){
$CWID->CWID = $request->input('CWID');
$CRN->CRN = $request->input('CRN');
$Date_Registered->Date_Registered = $request->input('Date_Registered');
$items = array('CWID'=>$CWID, 'CRN'=>$CRN, 'Date_Registered'=>$Date_Registered);
finalScheduleModel::insert($items);
}
When I test this insert function in postman it gives the error:
ErrorException: Creating default object from empty value in file
And the line the error is pointing to is the first line of the function
$CWID->CWID = $request->input('CWID');
I tried writing this function many different ways, but I keep getting errors along the same lines. It never reads any of the data being sent over. It might say something like trying to insert values CWID, CRN, Date_Registered (?,?,?) into final_schedule.
Try this see if this works for you.
public function insert(Request $request){
$array = [];
foreach (request()->all() as $value) {
array_push($array, ['CWID' => $value['CWID'], 'CRN' => $value['CRN'], 'Date_Registered' => $value['Date_Registered']]);
}
DB::table('final_schedule')->insert($array);
}

How to get a custom ModelState error message in ASP.NET Core when a wrong enum value is passed in?

I'm passing a model to an API action with a property called eventType which is a nullable custom enum.
If I pass a random value for eventType, such as 'h', it fails to serialise which is correct.
However, the error I get from the ModelState is not something I would want a public caller to see. It includes the line number and position (see below).
I've tried a number of options including a custom data annotation with no success.
Does anyone know how I could define a nicer custom message?
"Error converting value \"h\" to type
'System.Nullable`1[Custom.EventTypes]'. Path 'eventType', line 1,
position 80."
Most times the first error is usually the most important error or rather one that describes the situation properly. You can use this way to manipulate to get the first error message from the first key or change it to whatever you want if you wish to get all the error messages.
public ActionResult GetMyMoney(MyModel myModel)
{
string nss = ModelState.First().Key;
ModelError[] ern = ModelState[nss].Errors.ToArray();
string ndd = ern.First().ErrorMessage;
}
public class CustomFilter: IAsyncActionFilter
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (!context.ModelState.IsValid)
{
// You can pass custom object to BadRequestObjectResult method
context.Result = new BadRequestObjectResult(customObject);
}
}
}
You can write a custom filter like above mentioned and pass a custom object with your message.
Ref: this
IF you just want the error messages you can simply create a custom class of response and then
var response = new ResponseApi{
StatusCode = HttpStatusCode.BadRequest,
Message = "Validation Error",
Response = ModelState.Values.SelectMany(x => x.Errors).Select(x =>
x.ErrorMessage)
};
then just return the response or create a validation filter to handle validations globally.
/// <summary>
/// Validatation filter to validate all the models.
/// </summary>
public class ValidationActionFilter : ActionFilterAttribute
{
/// <inheritdoc/>
public override void OnActionExecuting(HttpActionContext actionContext)
{
ModelStateDictionary modelState = actionContext.ModelState;
if (!modelState.IsValid)
{
actionContext.Response = SendResponse(new ResponseApi
{
StatusCode= 400,
Message = "Validation Error",
Response = modelState.Values.SelectMany(x =>
x.Errors).Select(x => x.ErrorMessage)
});
}
}
private HttpResponseMessage SendResponse(ResponseApiresponse)
{
var responseMessage = new HttpResponseMessage
{
StatusCode = (HttpStatusCode)response.StatusCode,
Content = new StringContent(JsonConvert.SerializeObject(response)),
};
responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return responseMessage;
}
}

Find invalid values from JsonReaderException in Json.Net

I'm running the code below to purposely throw JsonReaderException. It correctly gives the exception message of "Could not convert string to boolean: aaa. Path 'Active', line 3, position 17."
Is there any way to get the value that has failed the validation directly from the JsonReaderException so I don't have to parse the exception message?
string json = #"{
'Email': 'james#example.com',
'Active': 'aaa',
'CreatedDate': '2013-01-20T00:00:00Z',
'Roles': [
'User',
'Admin'
]
}";
try
{
Account account = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(account.Email);
}
catch (JsonReaderException exc)
{
// Do Something
}
It appears that the offending value is not saved as a property in JsonReaderException. The only possible location for this value would be the Exception.Data dictionary, however Json.NET does not add anything here.
However, with some work you can leverage Json.NET's serialization error event handling functionality to directly access the bad value at the time the exception is thrown. First, define the following helper method and ErrorEventArgs subtype:
public class ErrorAndValueEventArgs : Newtonsoft.Json.Serialization.ErrorEventArgs
{
public object ReaderValue { get; } = null;
public ErrorAndValueEventArgs(object readerValue, object currentObject, ErrorContext errorContext) : base(currentObject, errorContext)
{
this.ReaderValue = readerValue;
}
}
public static partial class JsonExtensions
{
public static TRootObject Deserialize<TRootObject>(string json, EventHandler<ErrorAndValueEventArgs> error, JsonSerializerSettings settings = null)
{
using (var sr = new StringReader(json))
using (var jsonReader = new JsonTextReader(sr))
{
var serializer = JsonSerializer.CreateDefault(settings);
serializer.Error += (o, e) => error(o, new ErrorAndValueEventArgs(jsonReader.Value, e.CurrentObject, e.ErrorContext));
return serializer.Deserialize<TRootObject>(jsonReader);
}
}
}
Now you will be able to access the value of JsonReader.Value at the time the exception was thrown:
object errorValue = null;
try
{
Account account = JsonExtensions.Deserialize<Account>(json, (o, e) => errorValue = e.ReaderValue);
Console.WriteLine(account.Email);
}
catch (JsonException exc)
{
// Do Something
Console.WriteLine("Value at time of {0} = {1}, Data.Count = {2}.", exc.GetType().Name, errorValue, exc.Data.Count);
// Prints Value at time of JsonReaderException = aaa, Data.Count = 0.
}
Notes:
Since you must manually create your own JsonTextReader, you will need to have access to the JSON string (or Stream) for this approach to work. (This is true in the example shown in your question.)
A similar technique for capturing additional error information is shown in JsonSerializationException Parsing.
You might want to enhance ErrorAndValueEventArgs to also record JsonReader.TokenType. In cases where the reader is positioned at the beginning of a container (object or array) at the time an exception is thrown, JsonReader.Value will be null.
Demo fiddle here.

Slim3 how can I manage mixed content type errors

I need to set up a Slim application for html and json contents.
I will have just one errorhandler and it is supposed to reply as json for json enpoints and html error page for html views.
In the old fashined Slim (v.2) I have defined the view at the begining of the route, so I could check the view type (twig or json) to understand how to reply.
With the new Slim3 implementation the view will be send at the end of the route and, as far as I know, there is no way to define it earlier.
How can I manage this mixed content errors?
I thought to use the request content type header, but there is not a real rule that the content type should be coherent with the response, for example I can send some request as application/json and get a text/html reply, I also cannot use the Accept header because it can be missing or general */*.
I guess it depends how you decide, between returning json format or html.
For example, you may return error in json format when it is requested from AJAX otherwise you return html.
If you have error handler that returns html like following code
<?php namespace Your\App\Name\Space\Errors;
class HtmlErrorHandler
{
public function __invoke($request, $response, $exception)
{
$err = '<html><head></head><body>' .
'<div>code : ' . $exception->getCode() .
' message' . $exception->getMessage() '</div>';
return $response->withStatus(500)
->withHeader('content-Type : text/html')
->write($err);
}
}
and error handler that returns json,
<?php namespace Your\App\Name\Space\Errors;
class JsonErrorHandler
{
public function __invoke($request, $response, $exception)
{
$err = (object) [
'code' => $exception->getCode(),
'message' => $exception->getMessage(),
];
return $response->withStatus(500)->withJson($err);
}
}
You can compose them in another error handler class which select which error handler to return error response based on whether request coming from AJAX for not.
<?php namespace Your\App\Name\Space\Errors;
class Http500Error
{
private $jsonErrorHandler;
private $htmlErrorHandler;
public function __construct($jsonErrHandler, $htmlErrHandler)
{
$this->jsonErrorHandler = $jsonErrHandler;
$this->htmlErrorHandler = $htmlErrHandler;
}
public function __invoke($request, $response, $exception)
{
if ($request->isXhr()) {
$errHandler = $this->jsonErrorHandler;
} else {
$errHandler = $this->htmlErrorHandler;
}
return $errHandler($request, $response, $exception);
}
}
Or you may put certain variable in query string to indicate which format client want, then you can use
if ($request->getParam('format', 'html') === 'json') {
$errHandler = $this->jsonErrorHandler;
} else {
$errHandler = $this->htmlErrorHandler;
}
Then you injects error handler to container
use Your\App\Name\Space\Errors;
...
$app = new \Slim\App();
$c = $app->getContainer();
$c['errorHandler'] = function ($c) {
return new Http500Error(new JsonErrorHandler(), new HtmlErrorHandler());
};

Struts2 more than one action in one class

I'm using Struts2. I have two web forms that have the same code. I would like to eliminate one form. Here is the structure of my Struts project.
\Web Pages
form.jsp
\WEB-INF
\Content
error.jsp
form.jsp
success.jsp
\Source Packages
\action
MyAction.java
MyAction.java
package action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.*;
public class MyAction extends ActionSupport {
#Action(value = "foo", results = {
#Result(name = "input", location = "form.jsp"),
#Result(name = "success", location = "success.jsp"),
#Result(name = "error", location = "error.jsp")
})
public String execute() throws Exception {
if (user.length() == 1) {
return "success";
} else {
return "error";
}
}
private String user = "";
public void validate() {
if (user.length() == 0) {
addFieldError("user", getText("user required"));
}
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
I tried to eliminate form.jsp under \Web Pages by adding a new action method to MyAction.java.
#Action(value="bar", results = {
#Result(name = "success", location = "form.jsp"),
})
public String another() {
return "success";
}
But I got the following error when I go to http : //localhost .../bar.action
HTTP Status 404 - No result defined for action action.MyAction and result input
Your MyAction has an implementation of validate(), which means it is validation aware.
What's happening is that you're calling another, but validate() is kicking in (as it's in the interceptor stack). Validation is failing, and therefore sending to INPUT result, which is not defined in another.
You should
Add #SkipValidation to the another method if you don't want validation there
Add the INPUT result to another() if you want a default input result
On a more general note, when you get that kind of error (No result defined for action X and result input) it usually means you're either having validation errors, parameter population errors (eg: an exception in preparable).