RestAPI 호출시 발생한 ajax Error 0




문제는 CORS 설정때문이었다.


Cors 에 대한 내용을 추가해주자...



Startup.cs


    public class Startup

    {

        public IConfiguration Configuration { get; set; }


        public Startup(IConfiguration configuration)

        {

            Configuration = configuration;

        }


        // This method gets called by the runtime. Use this method to add services to the container.

        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940

        public void ConfigureServices(IServiceCollection services)

        {

            // services.AddMvc(); 보다 앞에 위치 시킨다. (이건 Test 해보지 않았다. ^^;)

            services.AddCors();


            services.AddMvc();


            services.AddDataAccess();

            services.AddBusinessLogics();


            var configBuilder = new ConfigurationBuilder()

               .SetBasePath(Directory.GetCurrentDirectory())

               .AddJsonFile("appsettings.json", optional: true);

            var config = configBuilder.Build();


            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

            }


            // app.UseMvc(); 보다 앞에 위치 시킨다.

            app.UseOptions();


            //app.UseCors(builder => 

            //    builder.AllowAnyOrigin()

            //    .AllowCredentials()

            //    .AllowAnyHeader()

            //    .AllowAnyMethod()

            //    //.WithMethods("POST,GET,PUT,PATCH,DELETE,OPTIONS")

            //);


            //app.UseCors(builder =>


            //    //builder.AllowAnyOrigin().AllowAnyMethod()

            //    //.WithHeaders(HeaderNames.ContentType, "Authorization", "X-Requested-With")

            

//    builder.WithOrigins("*")

            //    //.AllowAnyOrigin()

            //    .AllowCredentials()

            //    .WithMethods("POST,GET,PUT,PATCH,DELETE,OPTIONS")

            //    .AllowAnyHeader()

            //    //.WithHeaders("Authorization", "X-Requested-With")

            //    );


            app.UseMvc();


            app.UseMvcWithDefaultRoute();


        }

    }



OptionsMiddleware.cs

    public static class OptionsMiddlewareExtensions

    {

        public static IApplicationBuilder UseOptions(this IApplicationBuilder builder)

        {

            return builder.UseMiddleware<OptionsMiddleware>();

        }

    }


    public class OptionsMiddleware

    {

        private readonly RequestDelegate _next;

        private IHostingEnvironment _environment;


        public OptionsMiddleware(RequestDelegate next, IHostingEnvironment environment)

        {

            _next = next;

            _environment = environment;

        }


        public async Task Invoke(HttpContext context)

        {

            this.BeginInvoke(context);

            await this._next.Invoke(context);

        }


        private async void BeginInvoke(HttpContext context)

        {

            //context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

            ////context.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*", (string)context.Request.Headers["Origin"] });

            ////context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "Origin, X-Requested-With, Content-Type, Content-Type: application/json, Accept, Accept: application/json, Authorization" });

            //context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "*" });

            //context.Response.Headers.Add("Access-Control-Allow-Methods", new[] { "GET, POST, PUT, DELETE, OPTIONS" });

            //context.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });


            context.Response.Headers.Add("Access-Control-Allow-Origin", "*");

            context.Response.Headers.Add("Access-Control-Allow-Credentials", "true");

            // Added "Accept-Encoding" to this list

            //context.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "*" });

            context.Response.Headers.Add("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Requested-With, Accept, Accept-Version, Accept-Encoding, Content-Encoding, Content-Length, Content-MD5, Date, X-Api-Version, X-File-Name");

            context.Response.Headers.Add("Access-Control-Allow-Methods", "POST,GET,PUT,PATCH,DELETE,OPTIONS");


            if (context.Request.Method == "OPTIONS")

            {

                //context.Response.StatusCode = 200;

                //await context.Response.WriteAsync("OK");


                context.Response.StatusCode = (int)HttpStatusCode.OK;

                await context.Response.WriteAsync(string.Empty);

            }


        }

    }



Startup.cs 에서 


            .AllowAnyMethod() 대신 


            .WithMethods("POST,GET,PUT,PATCH,DELETE,OPTIONS") 로 변경해 보았는데.



Origin 과는 전혀 상관없는 오류가 발생했다. ㅡㅡ;

그렇다면 모든 Methos 를 열어줘야 한다는 이야기가 되는데... 그럼 안되겠죠? ㅋㅋ


그래서 app.UseCors(....) 를 사용하지 않고 위에 적어 놓은 Middleware 를 사용하기로 결정했다. 

Origins 의 경우는  Test 를 거쳐 변경할 예정이다.

Headers 의 경우도 현재는 Authorization, Content-Type, X-Requested-With 만 필요하지만 일단 다른 Header 들도 추가해 놓은 상태다.



ASP.NET Core 의 경우 ASP.NET 보다 유연하겠구나 라는 생각이 들긴하지만 서비스 내용을 바탕으로 설정해줘야 할 것들을 숙지하고 해둬야 하겠다.


이젠 WebSocket 을 붙여야 하는 상황인데...

Test 를 해보니 Socket 으로 가야할 녀석이 Controller 로 Routing 되는 걸 알게 되었다.


그럼 이만 Socket Test 하러... 슝~!




행복한 고수되셔요.


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Posted by woojja

댓글을 달아 주세요

VisualStudio Code 에서 React 개발환경을 설정하는 순서를 나열해 봤습니다.


Typescript

Webpack

React

을 구성했고 추가적으로 

react-hot-loader

Babel

TSLint


를 설정하는 방법을 기술하였습니다.


추후 화면 Capture 를 추가할 예정입니다. (일단은 제가 확인하기 위한 내용으로...)



<source path>\React\>mkdir typescript-react-webpack

<source path>\React\>cd typescript-react-webpack


<source path>\React\typescript-react-webpack>code .

<source path>\React\typescript-react-webpack>mkdir src

<source path>\React\typescript-react-webpack>mkdir build


npm config list


npm set init.author.name "<Your Name>"

npm set init.author.email "yourAccount@woojja.com"

npm set init.author.url "www.woojja.com"

npm set init.license "MIT"



<source path>\React\typescript-react-webpack>npm init -y


Wrote to 

<source path>\React\typescript-react-webpack\package.json:


######################  package.json  ###########################

{

  "name": "typescript-react-webpack",

  "version": "1.0.0",

  "description": "",

  "main": "index.js",

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "keywords": [],

  "author": "JH.Woo <woojja@bachilab.com> (www.bachilab.com)",

  "license": "MIT"

}

###############################################################



Part 1 — Typescript and Webpack


<source path>\React\typescript-react-webpack>npm install --save-dev typescript webpack webpack-cli


<source path>\React\typescript-react-webpack>copy con webpack.config.js


ctlr + z


######################  webpack.config.js  ###########################


var path = require("path");


var config = {

    mode: 'development',

  /*

   * app.ts represents the entry point to your web application. Webpack will

   * recursively go through every "require" statement in app.ts and

   * efficiently build out the application's dependency tree.

   */

  entry: ["./src/app.ts"],


  /*

   * The combination of path and filename tells Webpack what name to give to

   * the final bundled JavaScript file and where to store this file.

   */

  output: {

    path: path.resolve(__dirname, "build"),

    filename: "bundle.js"

  },


  /*

   * resolve lets Webpack now in advance what file extensions you plan on

   * "require"ing into the web application, and allows you to drop them

   * in your code.

   */

  resolve: {

    extensions: ["*", ".ts", ".tsx", ".js"]

  },


  module: {

    /*

     * Each loader needs an associated Regex test that goes through each

     * of the files you've included (or in this case, all files but the

     * ones in the excluded directories) and finds all files that pass

     * the test. Then it will apply the loader to that file. I haven't

     * installed ts-loader yet, but will do that shortly.

     */

    rules: [

      {

        test: /\.tsx?$/,

        exclude: /node_modules/,

        use: ['ts-loader']

      }

    ]

  }

};


module.exports = config;


###################################################################




<source path>\React\typescript-react-webpack>npm  install --save-dev ts-loader



make file : index.html, src/app.ts, and src/some_module.ts


##########################  src/some_module.ts  ########################

const greeting: string = "Hello World!";


export default greeting;

###################################################################


##########################  src/app.ts  ################################

import greeting from "./some_module";


console.log(greeting);

###################################################################


##########################  index.html ################################

<!DOCTYPE html>

<html>

  <head>

    <meta charset="utf-8">

    <title>Getting Started with Typescript, ReactJS, and Webpack</title>

  </head>

  <body>

    <script src="build/bundle.js"></script>

  </body>

</html>

###################################################################


<source path>\React\typescript-react-webpack2>copy con tsconfig.json

{

    "compilerOptions": {

      "jsx": "react",

      "module": "commonjs",

      "noImplicitAny": true,

      "outDir": "./build/",

      "preserveConstEnums": true,

      "removeComments": true,

      "target": "ES5"

    },

    "exclude": [

      "node_modules"

    ]

}

ctlr + z


<source path>\React\typescript-react-webpack>npm run build


index.html 실행



console 확인.




Part 2 — ReactJS


<source path>\React\typescript-react-webpack>npm install --save react react-dom


<source path>\React\typescript-react-webpack>npm install --save-dev @types/react @types/react-dom @types/react-router-dom // @types/webpack-env


############################## some_module.ts ==>  Hello.tsx #####################################

// Remember to rename your file to Hello.tsx and

// place it within your src/ directory

import * as React from "react";


interface HelloProps {

  name: string;

}


class Hello extends React.Component<HelloProps, {}> {

  render() {

    return <div>Hello, {this.props.name}</div>;

  }

}


export default Hello;

###################################################################



########################### app.ts ==>  app.tsx  ########################################

import * as React from "react";

import * as ReactDOM from "react-dom";

import Hello from "./Hello";


ReactDOM.render(

  <Hello name="Willson" />,

  document.getElementById("root")

);

###################################################################


##########################  index.html ###############################

<!DOCTYPE html>

<html>

  <head>

    <meta charset="utf-8">

    <title>Getting Started with Typescript, ReactJS, and Webpack</title>

  </head>

  <body>

    <!-- this is where our Hello component will get rendered into -->

    <div id="root"></div>


    <script src="build/bundle.js"></script>

  </body>

</html>

###################################################################



########################  webpack.config.js  ############################

var path = require("path");


var config = {

    mode: 'development',

  /*

   * app.ts represents the entry point to your web application. Webpack will

   * recursively go through every "require" statement in app.ts and

   * efficiently build out the application's dependency tree.

   */

  entry: ["./src/app.tsx"],


  /*

   * The combination of path and filename tells Webpack what name to give to

   * the final bundled JavaScript file and where to store this file.

   */

  output: {

    path: path.resolve(__dirname, "build"),

    filename: "bundle.js"

  },


  /*

   * resolve lets Webpack now in advance what file extensions you plan on

   * "require"ing into the web application, and allows you to drop them

   * in your code.

   */

  resolve: {

    extensions: ["*", ".ts", ".tsx", ".js"]

  },


  module: {

    /*

     * Each loader needs an associated Regex test that goes through each

     * of the files you've included (or in this case, all files but the

     * ones in the excluded directories) and finds all files that pass

     * the test. Then it will apply the loader to that file. I haven't

     * installed ts-loader yet, but will do that shortly.

     */

    rules: [

      {

        test: /\.tsx?$/,

        exclude: /node_modules/,

        use: ['ts-loader']

      }

    ]

  }

};


module.exports = config;

####################################################################


<source path>\React\typescript-react-webpack>npm run build



part 3 — Hot Module Replacement in React (react-hot-loader)


npm install --save-dev react-hot-loader


########################  webpack.config.js  #############################

const webpack = require('webpack');


module.exports = {

...,


plugins: [

new webpack.HotModuleReplacementPlugin()

], 

...


}


####################################################################


A huge development boost will give you react-hot-loader (Hot Module Replacement). 

It will shorten your feedback loop during development. 

Basically whenever you change something in your source code, 

the change will apply in your app running in the browser without reloading the entire page.


######################## app.tsx  ##################################

import * as React from "react";

import * as ReactDOM from "react-dom";

import Hello from "./Hello";


ReactDOM.render(

    <Hello name="Willson" />,

    document.getElementById("root")

  );


module.hot.accept();

####################################################################


참고 :

https://medium.com/@francesco.agnoletto/how-to-set-up-typescript-with-babel-and-webpack-6fba1b6e72d5


https://github.com/Kornil/simple-ts-react-app




import * as React from "react";

import * as ReactDOM from "react-dom";

// hot reload for development

import { AppContainer } from "react-hot-loader";


import App from "./App";


import "./style.scss";


const root = document.getElementById("root") as HTMLElement;


const render = (Component: React.SFC) => {

  ReactDOM.render(

    <AppContainer>

      <Component />

    </AppContainer>,

    root,

  );

};


render(App);


if (module.hot) {

  module.hot.accept("./App", () => {

    render(App);

  });

}


module.hot.accept();

####################################################################


Part 4 — Babel



<source path>\React\typescript-react-webpack>npm install --save-dev babel-core babel-loader

<source path>\React\typescript-react-webpack>npm install --save-dev @babel/core source-map-loader

<source path>\React\typescript-react-webpack>npm install --save-dev @babel/preset-typescript @babel/preset-react @babel/preset-env



<source path>\React\typescript-react-webpack>copy con .babelrc

{

  "presets": ["@babel/react", "@babel/typescript", ["@babel/env", { "modules": false }]]

}

ctrl + z



Tokenization is skipped for lines longer than 20k characters for performance reasons.



part 5 — Setting up TSLint


npm install --save-dev tslint tslint-react



########################  tslint.json  ##################################

{

  "extends": ["tslint:recommended", "tslint-react"],

  "rules": {}

}

####################################################################


행복한 고수되십시오. 


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\




Posted by woojja

댓글을 달아 주세요


안녕하세요? 


WebAPI 을 작성하면서 Autofac 을 사용해 보려는데...

이거 뭐... 현명한 선택인지... ^^;


Owin 이 포함되어야하므로...


Install-Package Autofac

Install-Package Autofac.Owin

Install-Package Autofac.WebApi2

Install-Package Autofac.WebApi2.Owin


행복한 고수되셔요.


woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




Posted by woojja

댓글을 달아 주세요


PowerShell 을 사용하여 MachineKey 를 작성하는 방법입니다.


Appendix A: How to generate a <machineKey> element

아래 Function 을 PowerShell 에 Copy & Paste 하여 Enter 를 쾅! 칩니다. ^^


# Generates a <machineKey> element that can be copied + pasted into a Web.config file.
function Generate-MachineKey {
  [CmdletBinding()]
  param (
    [ValidateSet("AES", "DES", "3DES")]
    [string]$decryptionAlgorithm = 'AES',
    [ValidateSet("MD5", "SHA1", "HMACSHA256", "HMACSHA384", "HMACSHA512")]
    [string]$validationAlgorithm = 'HMACSHA256'
  )
  process {
    function BinaryToHex {
        [CmdLetBinding()]
        param($bytes)
        process {
            $builder = new-object System.Text.StringBuilder
            foreach ($b in $bytes) {
              $builder = $builder.AppendFormat([System.Globalization.CultureInfo]::InvariantCulture, "{0:X2}", $b)
            }
            $builder
        }
    }
    switch ($decryptionAlgorithm) {
      "AES" { $decryptionObject = new-object System.Security.Cryptography.AesCryptoServiceProvider }
      "DES" { $decryptionObject = new-object System.Security.Cryptography.DESCryptoServiceProvider }
      "3DES" { $decryptionObject = new-object System.Security.Cryptography.TripleDESCryptoServiceProvider }
    }
    $decryptionObject.GenerateKey()
    $decryptionKey = BinaryToHex($decryptionObject.Key)
    $decryptionObject.Dispose()
    switch ($validationAlgorithm) {
      "MD5" { $validationObject = new-object System.Security.Cryptography.HMACMD5 }
      "SHA1" { $validationObject = new-object System.Security.Cryptography.HMACSHA1 }
      "HMACSHA256" { $validationObject = new-object System.Security.Cryptography.HMACSHA256 }
      "HMACSHA385" { $validationObject = new-object System.Security.Cryptography.HMACSHA384 }
      "HMACSHA512" { $validationObject = new-object System.Security.Cryptography.HMACSHA512 }
    }
    $validationKey = BinaryToHex($validationObject.Key)
    $validationObject.Dispose()
    [string]::Format([System.Globalization.CultureInfo]::InvariantCulture,
      "<machineKey decryption=`"{0}`" decryptionKey=`"{1}`" validation=`"{2}`" validationKey=`"{3}`" />",
      $decryptionAlgorithm.ToUpperInvariant(), $decryptionKey,
      $validationAlgorithm.ToUpperInvariant(), $validationKey)
  }
}


그러면 추가한 Generate-MachineKey 를 사용해 봐야겠죠?!


ASP.NET 4.0 application 에서는 Machine Key 작성시 Option Parameter 를 주지 않아도 됩니다.


PS> Generate-MachineKey

<machineKey decryption="AES" decryptionKey="..." validation="HMACSHA256" validationKey="..." />


하지만 ASP.NET 2.0 과 3.5 application 에서는 HMACSHA256 을 지원하지 않으므로 Parameter 로 "SHA1" 을 넣어줘야 한다네요.


PS> Generate-MachineKey -validation sha1

<machineKey decryption="AES" decryptionKey="..." validation="SHA1" validationKey="..." />


ASP.NET 그리고 Web.config 파일에 MachineKey element 를 추가해 줍니다.


<configuration>

  <system.web>

    <machineKey ... />

  </system.web>

</configuration>


행복한 고수되셔요.



woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




'Security' 카테고리의 다른 글

[SECURITY] MachineKey 만들기  (0) 2018.08.03
Posted by woojja

댓글을 달아 주세요

2018. 7. 24. 20:30



Time Zone Identifiers 정보입니다.

https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/bb384272%28v%3dvs.90%29


UTC Time 을 Localtime 으로 변경하시려면...


TimeZoneInfo koreaStandardTimeZone 

= TimeZoneInfo.FindSystemTimeZoneById("Korea Standard Time");

DateTime koreaStandardTime 

= TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, koreaStandardTimeZone);

MessageBox.Show(koreaStandardTime.ToString("yyyy-MM-dd HH:mm:ss"));



이렇게 사용하시면 되겠습니다.



행복한 고수되셔요. ^^

woojja ))*

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\




'.NET' 카테고리의 다른 글

[.NET] Time Zone Identifiers  (2) 2018.07.24
[.NET] Clone  (0) 2017.05.31
[.NET] Collection was modified; enumeration operation may not execute.  (4) 2017.05.30
[.NET] .NET Core Roadmap  (0) 2017.02.10
[.NET] Bit 연산에 대한 내용입니다.  (0) 2014.05.07
[.NET] Telerik Code Convertor  (0) 2014.05.07
Posted by woojja

댓글을 달아 주세요

  1. 2018.07.24 21:20

    "특정" 로컬 타임으로 변경할 때는 Timezone을 이용하면 되지만, 운영체제의 기본 로컬 타임 존으로 변경하려면 그냥 ToLocalTime을 호출해도 됩니다. ^^

    DateTime utcNow = DateTime.UtcNow;
    DateTime localNow = utcNow.ToLocalTime();

    • 2018.08.03 14:14 신고

      Chat Bot 의 Activity 라는 녀석은 기본적으로 UTC Time 으로 가지고 다니고 있어서 Local Time 으로 보여주려면 요롷게 사용하라는... 글 올린이의 사려깊은... ^^;